# Conversion from decimal to negabinary and vice versa in Haskell

Recently I set about to writing conversion functions in Haskell between decimal and negabinary. I tried to write them in as much functional a style as possible, also aiming at brevity. Below I present my take at the task. I'd be interested in your refinements of the method I employ or any comments whatsoever.

These are my two functions for converting back and forth:

type NegaBinary = String

dec2negbin :: Int -> NegaBinary
dec2negbin = reverse .
map intToDigit .
unfoldr (\x -> if x==0 then Nothing else Just(abs(xrem x (-2)), xdiv x (-2)))
where
xrem a b = if b > 0 then rem a b else (-(rem a (-b)))
xdiv a b = if b > 0 then div a b else (-(div a (-b)))

negbin2dec :: NegaBinary -> Int
negbin2dec = sum . map (\x -> (snd x)*(-2)^(fst x)) . zip [0..] . reverse . map digitToInt


I defined the NegaBinary type just for clarity. The dec2negbin employs the unfoldr function for sequential divisions and remainder calculations. I also used two local functions: xrem and xdiv, because the standard functions (rem and div) had the undesirable behavior of always approaching the dividend from below (meaning that in div a b => c b*c is always lower than a). What I wanted is for it to approach in the direction from zero, so the behavior is different for positive and negative dividends. I know the definition of dec2negbin is a bit bulky, so improvements are welcome.

A couple of things I noticed:

xrem and xdiv are exactly the same except they use a different division function. You could therefore replace them with a single function that takes the type of division as a parameter:

dec2negbin :: Int -> NegaBinary
dec2negbin = reverse .
map intToDigit .
unfoldr (\x -> if x==0 then Nothing else Just(abs(doDiv rem x (-2)), doDiv div x (-2)))
where
doDiv division a b = if b > 0 then division a b else (-(division a (-b)))


In your second function you could use zipWith which applies a given function whilst zipping instead of doing a zip then a map:

negbin2dec :: NegaBinary -> Int
negbin2dec = sum . zipWith raise [0..] . reverse . map digitToInt
where
raise e x = x * (-2) ^ e