Reputation: 2911
I'm learning haskell and am currently trying to parse Integers and Floats from strings.
However, when trying my readNum function on "342" or any "number" that doesn't have a single or more non-numeric characters ghci reports to me:
* Exception: parse.hs:125:18-46: Irrefutable pattern failed for pattern (i, (a : as))
data Token
= IntTok Int | FloatTok Float | EOF
readNum :: String->(Token, String)
readNum [] = (EOF, [])
readNum xs = let (i, (a:as)) = span isDigit xs --This is line 125
in (case a of
('.') -> let (j, (b:c:bs)) = span isDigit as
in (if ((toLower b) == 'e' && (c == '+' || c == '-' || (isDigit c)))
then (let (k, d) = span isDigit bs in (FloatTok (read (concat [i,[a],j, [b],[c],k])::Float), d))
else (FloatTok (read (concat [i,[a],j])::Float), (b:c:bs)))
_ -> (IntTok (read i::Int), (a:as)))
Is there a better way to handle the case when span isDigit xs
returns an empty list as the second element of the tuple?
-Thanks
Upvotes: 2
Views: 1102
Reputation: 32455
You're getting the error because if you use a simple Integer like "342"
then span isDigit "342"
is just ("342",[])
, which can't match (l,a:as)
. A pattern that is supposed to always match is called an irrefutable pattern. As you've found out, patterns in let bindings are irrefutable, so...
You need to to stick to patterns that will always match in a let binding. For example you could do
readNum xs = let (i, ps) = span isDigit xs
in (case ps of
('.':as) -> let (j, qs) = span isDigit as in case qs of
b:c:bs -> if ..........
_ -> error "not enough stuff after decimal number"
_ -> ....
I gave a silly error message, but clearly you should write more sensible code there.
Upvotes: 6