2013-04-09 38 views
2

我有一個函數如何完全中止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(另一個數據I定義類型),但它實際上接收輸入IO退出碼。足夠公平 - exit_and_report_mismatch正在返回不是Val的IO ExitCode。

如何從「exit_and_report_type_mismatch」中完全中止Haskell程序?我已經讀了一些關於Haskell的異常,但是這些解釋要麼沒有意義,要麼提到必須從主函數調用ExitWith,這不是一個選項。

回答

9

這是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)。

+0

也考慮使用['undefined'](http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:undefined),這有時更適合可讀性。但兩者只能用於標記程序員錯誤,而不是用戶錯誤。 – Beetle 2013-04-09 18:14:58

+0

@Antal S-Z謝謝 - 這正是我正在尋找的,並感謝您最後的注意。我不確定你的意思是部分類型,因爲在我的函數中使用錯誤沒有導致Haskell抱怨類型錯誤? – nebffa 2013-04-11 09:02:03

+0

@nebffa:部分函數不是局部類型 - 在某些方面幾乎相反:-)考慮'head :: [a] - > a'。當然,這是很好的類型;然而,有時候,它並不實際返回,而是崩潰。這就是'head'部分的意思,head []'不是一個值。儘管* head []是很好的類型,這就是我所說的「幾乎相反」的意思。如果一個函數f是全部的(比如'fst ::(a,b) - > a'),那麼'f x'保證爲所有'x'產生一個值。 (我忽略了無限和部分數據,比如'[1 ..]'和'undefined',但這是基本思想。) – 2013-04-11 16:19:02

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可能工作一樣,雖然。

相關問題