the code below produces a "non-exhaustive pattern in function asd"
data Token = TokenPlus
| TokenMinus
| TokenMal
| TokenGeteilt
| TokenKlammerAuf
| TokenKlammerZu
| TokenInt Int
deriving(Eq,Show)
asd (x:xs) = if x == '+' then (x, TokenPlus): (asd xs)
else (x, TokenInt 1): (asd xs)
Let's say i wanted to catch this kind of error, i would use catch (asd "my_string") my_handler_function
. Fine until here, but what Type is 开发者_高级运维":t 'non-exhaustive pattern' "
made of ?
Pattern match failure exceptions are of type PatternMatchFail
. The base exceptions are all defined in Control.Exception.
Below is a use of Control.Exception.catch to catch a pattern match failure of the type you're talking about. Here, my operation and handler are both of type IO ()
, but you
can make it anything you want - if the operatio is IO Int
then the exception handler could return a default IO Int
.
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Exception as X
func = X.catch (print $ asd []) printErr
printErr :: SomeException -> IO ()
printErr e = do
case fromException e of
Just (x:: PatternMatchFail) -> putStrLn "I caught the exception"
>> print x
nothing -> return ()
asd :: [Int] -> [Int]
asd (x:xs) = xs
(x:xs)
doesn't match []
, but since it will match '1':[]
(the unsugared version of [1]
), you'll get a pattern match failure when you handled every element just because you didn't tell the program what to do at the end (namely, to stop). There is absolutely zero reason to let this happen, just add a base case for the empty list:
asd [] = []
By the way, this is just a hand-rolled version of map
. It can be written as
asd xs = map (\x -> if x == '+' then (x, TokenPlus) else (x, TokenInt 1)) xs
精彩评论