Haskell“非穷举模式异常”

时间:2011-05-22 13:53:47

标签: haskell error-handling design-patterns

下面的代码会产生“函数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)

假设我想抓住这种错误,我会使用catch (asd "my_string") my_handler_function。很好,直到这里,但":t 'non-exhaustive pattern' "的类型是什么?

2 个答案:

答案 0 :(得分:7)

(x:xs)[]不匹配,但由于它与'1':[][1]的未标注版本)匹配,因此当您启用模式匹配失败时处理每个元素只是因为你没有告诉程序最后要做什么(即停止)。绝对没有理由让这种情况发生,只需为空列表添加一个基本案例:

asd [] = []

顺便说一句,这只是map的手动版本。它可以写成

asd xs = map (\x -> if x == '+' then (x, TokenPlus) else (x, TokenInt 1)) xs

答案 1 :(得分:7)

模式匹配失败异常属于PatternMatchFail类型。基本异常都定义为in Control.Exception

下面是使用Control.Exception.catch来捕获您正在讨论的类型的模式匹配失败。在这里,我的操作和处理程序都是IO ()类型,但是你 可以使它成为你想要的任何东西 - 如果操作是IO Int,那么异常处理程序可以返回默认的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