4

我有一个功能

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 正在返回不是 Val 的 IO ExitCode。

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

4

2 回答 2

11

这是error为了什么。从文档中:

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

例如:

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

The effect of putStrLn is ignored, and the program terminates as soon as the value produced by error is demanded (lazy evaluation means that just putting error somewhere doesn't immediately cause an error; as you might or might not expect, let x = error "Message" in putStrLn "Printed" causes no errors). It is possible to catch these exceptions with the functions from Control.Exception.Base, such as catch, but I've never done this nor have I seen this done.

Also, as a final note, consider avoiding the use of error. Partial functions (functions that aren't defined over their entire input domain) are best avoided when possible, as it's much easier to reason about your code with the stronger guarantees total functions provide. It's nice when, as for total functions, f :: A -> B really means "the function f returns something of type B"; for partial functions, f :: A -> B means only "if the function f returns, then what it returns is of type B". In your case, this might mean having a type like interpretExpr :: Vars -> Expr -> Either RuntimeError Val, or something suitably isomorphic (in the simplest case, perhaps data Result = Error String | Value Val, and interpretExpr :: Vars -> Expr -> Result).

于 2013-04-09T10:22:37.293 回答
-1

这将做到:

import System.IO.Unsafe

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

不过,函数错误可能会起作用。

于 2013-04-09T08:16:13.690 回答