如何完全中止Haskell运行时?

neb*_*ffa 3 haskell

我有一个功能

import System.Exit

exit_and_report_type_mismatch :: String -> IO ExitCode
exit_and_report_type_mismatch error_message = do
    putStrLn error_message
    exitFailure
Run Code Online (Sandbox Code Playgroud)

和另一部分像这样

interpret_expr :: Vars -> Expr -> Val        
interpret_expr vars (Plus (ConsE _ _) (NumE _)) = exit_and_report_type_mismatch "Type Error: Can only concatenate list (not int) to list"
Run Code Online (Sandbox Code Playgroud)

Haskell向我抱怨它期待类型Val(我定义的另一种数据类型),但实际上它接收类型IO Exitcode.足够公平 - exit_and_report_mismatch返回的IO ExitCode不是Val.

如何从"exit_and_report_type_mismatch"中完全中止Haskell程序?我已经阅读了一些关于Haskell异常的内容,但是解释要么没有意义,要么提到必须从main函数调用ExitWith,这不是一个选项.

Ant*_*sky 10

error是为了什么.从文档:

error :: [Char] -> a
error 停止执行并显示错误消息.

例如:

zsh% runhaskell <<<'main = putStrLn (error "Message") >> print "Not reached."'
runghcXXXX7729.hs: Message
Run Code Online (Sandbox Code Playgroud)

putStrLn忽略效果,并且一旦error需要生成的值,程序就会终止(延迟评估意味着只是放在error某处不会立即导致错误;正如您可能或可能不期望的那样,不会let x = error "Message" in putStrLn "Printed"导致错误).它可以捕获这些异常与功能Control.Exception.Base,如catch,但我从来没有这样做,也没看到这件事.

另外,作为最后一点,请考虑避免使用error.在可能的情况下,最好避免使用部分函数(未在整个输入域中定义的函数),因为使用总函数提供的更强保证更容易推理代码.当总函数f :: A -> B真正意味着"函数f返回类型B" 时,这是很好的; 对于部分函数,f :: A -> B仅表示" 如果函数f返回,则返回的类型为B".在你的情况下,这可能意味着有类似的类型interpretExpr :: Vars -> Expr -> Either RuntimeError Val,或适当同构的东西(在最简单的情况下,也许data Result = Error String | Value Val,和interpretExpr :: Vars -> Expr -> Result).