在Haskell中,异常只能在抛出后立即捕获,并且不像Java或Python一样被传递。下面是一个简短的例子:
{-# LANGUAGE DeriveDataTypeable #-}
import System.IO
import Control.Monad
import Control.Exception
import Data.Typeable
data MyException = NoParseException String deriving (Show, Typeable)
instance Exception MyException
-- Prompt consists of two functions:
-- The first converts an output paramter to String being printed to the screen.
-- The second parses user's input.
data Prompt o i = Prompt (o -> String) (String -> i)
-- runPrompt accepts a Prompt and an output parameter. It converts the latter
-- to an output string using the first function passed in Prompt, then runs
-- getline and returns user's input parsed with the second function passed
-- in Prompt.
runPrompt :: Prompt o i -> o -> IO i
runPrompt (Prompt ofun ifun) o = do
putStr (ofun o)
hFlush stdout
liftM ifun getLine
myPrompt = Prompt (const "> ") (\s -> if s == ""
then throw $ NoParseException s
else s)
handleEx :: MyException -> IO String
handleEx (NoParseException s) = return ("Illegal string: " ++ s)
main = catch (runPrompt myPrompt ()) handleEx >>= putStrLn
运行程序后,当你仅按下[Enter]而没有输入任何内容时,我应该会看到输出:
Illegal string:
。但实际上出现了:prog: NoParseException ""
。假设现在Prompt
类型和runPrompt
函数在模块外定义在通用库中,并且不能更改以处理传递给Prompt构造函数的函数中的异常。那么我如何在不更改runPrompt
的情况下处理异常呢?我考虑过添加第三个字段到
Prompt
中来注入异常处理函数,但这种方式对我来说似乎很丑陋。有更好的选择吗?