如何完全中止Haskell运行时?

时间:2013-04-09 07:59:19

标签: haskell

我有一个功能

import System.Exit

exit_and_report_type_mismatch :: String -> IO ExitCode
exit_and_report_type_mismatch error_message = do
    putStrLn error_message
    exitFailure

和另一部分像这样

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"

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

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

2 个答案:

答案 0 :(得分:10)

这是error的用途。来自文档:

  

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

例如:

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

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 ValinterpretExpr :: Vars -> Expr -> Result)。

答案 1 :(得分:0)

这样做:

import System.IO.Unsafe

exit_and_report_type_mismatch :: String -> a
exit_and_report_type_mismatch error_message = unsafePerformIO $ do
    putStrLn error_message
    exitFailure

函数error可能会起作用。