开发者

Haskell "Non-Exhaustive pattern exception"

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜