1

I am learning Haskell and recursion and different types in Haskell is making my brain hurt. I am trying to create a recursive function that will take a 32 bit binary number string and convert it to a decimal number. I think my idea for how the recursion will work is fine but implementing it into Haskell is giving me headaches. This is what I have so far:

bin2dec :: String -> Int
bin2dec xs = ""
bin2dec (x:xs) = bin2dec xs + 2^(length xs) *  x

The function is supposed to take a 32 bit number string and then take off the first character of the string. For example, "0100101010100101" becomes "0" and "100101010100101". It then should turn the first character into a integer and multiply it by 2^length of the rest of the string and add it to the function call again. So if the first character in the 32 bit string is "1" then it becomes 1 * 2^(31) + recursive function call.

But, whenever I try to compile it, it returns:

traceProcP1.hs:47:14: error:
    * Couldn't match type `[Char]' with `Int'
      Expected: Int
        Actual: String
    * In the expression: ""
      In an equation for `bin2dec': bin2dec xs = ""
   |
47 | bin2dec xs = ""
   |              ^^

traceProcP1.hs:48:31: error:
    * Couldn't match expected type `Int' with actual type `Char'
    * In the second argument of `(+)', namely `2 ^ (length xs) * x'
      In the expression: bin2dec xs + 2 ^ (length xs) * x
      In an equation for `bin2dec':
          bin2dec (x : xs) = bin2dec xs + 2 ^ (length xs) * x
   |
48 | bin2dec (x:xs) = bin2dec xs + 2^(length xs) *  x
   |                               ^^^^^^^^^^^^^^^^^^

I know this has to do with changing the datatypes, but I am having trouble type casting in Haskell. I have tried type casting x with read and I have tried making guards that will turn the '0' into 0 and '1' into 1, but I am having trouble getting these to work. Any help would be very appreciated.

1
  • 1
    Aside from the typing problems, it's worth pointing out that you've got the patterns in the wrong order. Matching goes top-down and stops at the first match - so once this is fixed so that it compiles, you'll get 0 for any string. You need to either switch the order, or change the pattern so that it doesn't catch everything, but just the empty string. Commented Mar 28, 2021 at 10:31

1 Answer 1

2

There is no casting. If you want to convert from one type to another, there needs to be a function with the right type signature to do so. When looking for any function in Haskell, Hoogle is often a good start. In this case, you're looking for Char -> Int, which has several promising options. The first one I see is digitToInt, which sounds about right for you.

But if you'd rather do it yourself, it's quite easy to write a function with the desired behavior, using pattern matching:

bit :: Char -> Int
bit '0' = 0
bit '1' = 1
bit c = error $ "Invalid digit '" ++ [c] ++ "'"
Sign up to request clarification or add additional context in comments.

3 Comments

I see. Thank you! That makes much more sense. What would you do in a situation where there's not a small amount of options like 0 and 1 and you are trying to convert them all?
There's no way around it: pattern matching is the fundamental way to consume data in Haskell. You either need to write more patterns, or use some other function that already does that for you, like ord :: Char -> Int.
@EMC, ord comes from Data.Char and is the same (for characters) as the polymorphic fromEnum function available from the prelude (without imports). These functions don't actually match on all the possible characters; they use the internal representation of Char to do their jobs efficiently and compactly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.