For my homework assignment, I need to convert a hexadecimal string to a base-10 integer using a recursive function (with as many helper methods as necessary).
This is what I've got so far:
-- Question 1, part (c):
hexChar :: Char -> Integer
hexChar ch
| ch == '0' = 0
| ch == '1' = 1
| ch == '2' = 2
| ch == '3' = 3
| ch == '4' = 4
| ch == '5' = 5
| ch == '6' = 6
| ch == '7' = 7
| ch == '8' = 8
| ch == '9' = 9
| ch == 'A' = 10
| ch == 'B' = 11
| ch == 'C' = 12
| ch == 'D' = 13
| ch == 'E' = 14
| ch == 'F' = 15
| otherwise = 0
parseHex :: String -> Integer
parseHex hxStr
| length hxStr /= 0 = (hexChar(last(hxStr)))+(10*parseHex(init(hxStr)))
| otherwise = 0
However, this does not produce the correct results. Does anyone know of the correct way to do this?
Now if you're a Haskell hacker, you'll probably laugh about that, but as a newbie I initially had to search for quite a bit in order to find the appropriate functions. So my colleague Matthias found a function called digitToInt which basically converts a Char into an Int type.
Haskell strings are implemented as linked lists, so length hxStrtakes time proportional to the length of hxStr. In contrast not (null hxStr)takes constant time to compute.
parseHex :: String -> Integer parseHex [] = 0 parseHex hxStr = hexChar (last hxStr) + 16 * parseHex (init hxStr)) It's unfortunate that you can't pattern match on hStrright away because you need initand lastinstead of headand tail.
If you are unfamiliar with Haskell's typeclasses, just know that you might have to tell Haskell what type you want to read it as: You don't always have to do this, if Haskell has some other way of knowing what type you want, like if you proceed to do arithmetic with it.
You are really close. your error is on this line:
| length hxStr /= 0 = (hexChar(last(hxStr)))+(10*parseHex(init(hxStr)))
Think about why you are multiplying by 10. Remember ... Hexadecimal is base 16.
Now that you got the right answer, you should consider the style. Using pattern matching, this looks clearer already:
parseHex :: String -> Integer
parseHex [] = 0
parseHex hxStr = (hexChar(last(hxStr)))+(16*parseHex(init(hxStr)))
And it's also more efficient, as you don't need to evalute length hxStr
(which is O(N)) at each recursive call to decide which case applies. Total runtime goes from O(N**2) to O(N).
It looks even better when you drop some parentheses, as groovy suggested:
parseHex :: String -> Integer
parseHex [] = 0
parseHex hxStr = hexChar (last hxStr) + 16 * parseHex (init hxStr))
It's unfortunate that you can't pattern match on hStr
right away because you need init
and last
instead of head
and tail
. But you can mitigate that using reverse
and a helper:
parseHex :: String -> Integer
parseHex hxStr = go (reverse hxStr)
where go [] = 0
go (x:xs) = hexChar x + 16 * parseHex xs
That last one may be just a matter of taste though. hexChar
also becomes shorter:
hexChar '0' = 0
hexChar '1' = 1
... -- other cases here
hexChar _ = 0 -- 'otherwise' case; maybe throw an error instead?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With