是否可以有一个返回Int的函数以在出错时关闭程序?例如,以选定的值退出吗?
这是我的代码:
example :: String -> Int
example s = do
let j = read s
case j of
0 -> j
_ -> exitWith (exitFailure: 84)
我只想在非IO函数中的错误时停止程序,我找不到其他方法,只能使用“错误”函数,该函数不返回任何值。
答案 0 :(得分:2)
评论中的一个选项可能是:
example :: String -> Maybe Int
example s = do
let j = read s
case j of
0 -> Just j
_ -> Nothing
,然后,每当您使用它时,都可以对Maybe值进行模式匹配。这与“退出程序”不同。但这是处理失败的一种方式。
其他方法是使用Either
type ErrorMsg = String
example :: String -> Either ErrorMsg Int
example s = do
let j = read s
case j of
0 -> Right j
_ -> Left "exitFailure: 84"
答案 1 :(得分:2)
这是利用异常的替代方法。
首先,我们声明一个自定义的异常类型,其中包含我们的ExitCode
import Control.Exception
import System.Exit
data TerminationException = TE ExitCode
deriving Show
instance Exception TerminationException where
然后,我们可以在纯代码中使用它,并根据需要引发异常。
example :: String -> Int
example s = let
j = read s
in case j of
0 -> j
_ -> throw (TE (ExitFailure 84))
请注意,如果输入字符串未解析为数字,则上述read
将使程序崩溃。我将其包括在内是为了尽可能接近原始代码,但最好使用readMaybe
或reads
。
然后我们可以定义一个小的异常处理程序。
withExit :: IO a -> IO a
withExit action = action `catch` (\(TE code) -> exitWith code)
最后,我们需要使用处理程序将main
包装起来,如下所示。
main :: IO ()
main = withExit $ do
putStrLn "hello 1"
print (example "0") -- passes
putStrLn "hello 2"
print (example "1") -- ** --
putStrLn "hello 3"
以上main
会在标记为**
的行触发异常。在那里,print
未被执行任何操作,并且程序返回了84
中指定的返回代码example
。