Good evening everyone, I'm new to haskell. I'm trying to sum up a list of reading a string Unicode values and store them in a list and then sum the integers up.
getLetterUnicodeValue :: Char -> Int
getLetterUnicodeValue l = (ord l) - 64
unicodeValueList :: String -> [Int]
unicodeValueList x = getLetterUnicodeValue (head x) : unicodeValueList (tail x)
total :: [Int] -> Int
total [] = 0
total x = (head x) + (total (tail x))
I got the error of empty list when the string come to the last character and the sum up function cannot successfully execute. Is there any way to stop the function unicodeValueList
when it comes to its end.
*** Exception: Prelude.head: empty list
The surest way to avoid this exception is not to use head
. Instead you can use pattern matching to get the head and tail of a list:
unicodeValueList (x:xs) = getLetterUnicodeValue x : unicodeValueList xs
total (x:xs) = x + total xs
This way x
and xs
will only be available when the list is non-empty and it is guaranteed that you never accidentally access the head or tail of an empty list.
Of course now you'll get a warning that the pattern match is incomplete: You don't specify what should happen when the list is empty. Of course this was true before as well, but now that you use pattern matching the compiler can actually see this and warn you about it (whereas the previous code crashed at runtime without any prior warning).
So what should be done when the list is empty? Well, an empty string contains no unicode values, right? So it should return the empty list when the input is empty:
unicodeValueList [] = []
Of course you don't need pattern matching to fix your error. You could just use an if
to make sure that you only call head
and tail
when the list is not empty. But if you do that, the compiler won't be able to verify that your checks are in order. If you use pattern matching and avoid the unsafe head
and tail
functions completely, you'll never be able to accidentally access the head or tail of an empty list and the compiler will warn you if you ever forget to consider that the list might be empty.
Yep, you just will have to pattern match in unicodeValueList
unicodeValueList :: String -> [Int]
unicodeValueList [] = []
unicodeValueList (x:xs) = getLetterUnicodeValue x : unicodeValueList xs
Note this could be written more nicely as unicodeValueList = map getLetterUnicodeValue
. The reason you are getting the error for head
is that your recursion had no base case - it keeps trying to recurse, even when it has reached the empty list.
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