你如何处理Haskell中的错误?假设我有分裂功能。如果可以执行除法,则返回true,否则返回false。
di :: Int -> Bool
di a b = a `div` b
如何捕获此类场景中的异常,以便返回布尔值?如何捕获所有异常,而不仅仅是特定类型的异常?我知道我可以检查b是否为零,但我只是想知道错误处理。
更新: 这是我到目前为止所做的。但是我遇到类型不匹配错误。任何人都可以指出我如何解决这个问题?
di :: Int -> Int -> Bool
di a b = do
result <- try (a `div` b) :: IO (Either SomeException Bool)
case result of
Left ex -> False
Right val -> True
错误
Couldn't match type ‘IO b0’ with ‘Bool’
Expected type: IO (Either SomeException Bool)
-> (Either SomeException Bool -> IO b0) -> Bool
Actual type: IO (Either SomeException Bool)
-> (Either SomeException Bool -> IO b0) -> IO b0
答案 0 :(得分:1)
您的代码存在一些问题:
di
在IO monad中运行,因此结果类型必须为IO Bool
try
需要进行IO计算,但div a b
是纯值,因此您需要使用return
来提升它。di
返回IO Bool
,因此最后一个case语句需要return
来将case表达式提升为IO计算。这是di
版本的类型检查:
di' :: Int -> Int -> IO Bool
di' a b = do
r <- try (return (div a b)) :: IO (Either SomeException Int)
return $ case r of
Left _ -> False
Right _ -> True
但是,此版本将为所有输入返回True
。原因是由于延迟评估,div
函数实际上从未被调用过。
解决此问题的一种方法是使用BangPatterns
编译指示强制进行评估:
{-# LANGUAGE BangPatterns #-}
di' :: Int -> Int -> IO Bool
di' a b = do
r <- try (let !x = div a b in return x) :: IO (Either SomeException Int)
return $ case r of
Left _ -> False
Right _ -> True
ghci> di' 3 0
False
ghci> di' 3 1
True
另请参阅此SO问题:How to catch a divide by zero error in Haskell?,了解有关如何仅捕获算术异常的详细信息。