是否可以使用当前返回类型在Haskell中退出函数?

时间:2019-11-04 15:21:19

标签: haskell error-handling

是否可以有一个返回Int的函数以在出错时关闭程序?例如,以选定的值退出吗?
这是我的代码:

example :: String -> Int
example s = do
let j = read  s
case j of
    0 -> j
    _ -> exitWith (exitFailure: 84)

我只想在非IO函数中的错误时停止程序,我找不到其他方法,只能使用“错误”函数,该函数不返回任何值。

2 个答案:

答案 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将使程序崩溃。我将其包括在内是为了尽可能接近原始代码,但最好使用readMaybereads

然后我们可以定义一个小的异常处理程序。

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