1

我得到了一些代码,例如:

setA :: Integer -> Integer
setA 3 = 5
setA 5 = 6
setA 7 = error "some error one"
setA _ = error "some error two"

现在我尝试编写另一个函数

checkError :: Integer -> Bool
checkError x = if HERE_TO_CHECK_IF setA x RETURNS some error two
                then False
                else True

但我该怎么做呢?

谢谢

4

4 回答 4

7

正如其他答案中已经说过的那样,您应该避免使用error,而是使用

setA :: Integer -> Either String Integer
setA 3 = Right 5
setA 5 = Right 6
setA 7 = Left "some error one"
setA _ = Left "some error two"

checkError :: Either String Integer -> Bool
checkError (Left _)  = False
checkError (Right _) = True

但是如果你不能做到这一点,请查看勺子包的源代码,看看如何做你的教授要求的。这很恶心。

然后你可以说

checkError :: Integer -> Bool
checkError x = case teaspoon x of
    Nothing -> False
    Just _  -> True
于 2013-04-30T09:25:11.633 回答
3

据我了解,error调用并不意味着被调用者捕获 - 如果您希望错误可以恢复,该setA函数应该使用其他一些机制(如Either)。如果您坚持要捕获error,您可以在 IO monad 中这样做,请参阅此相关问题

于 2013-04-30T09:05:41.040 回答
2

你的setA函数不正确。如果您希望函数能够返回错误值,您应该使用Either

setA :: Integer -> Either String Integer
setA 3 = Right 5
setA 5 = Right 6
setA 7 = Left "some error one"
setA _ = Left "some error two"

检查错误很简单:

checkError :: Either String Integer -> Bool
checkError = either (const True) (const False)
于 2013-04-30T08:57:53.917 回答
1

虽然error应该只用于不可恢复的坏状态(所以不需要被捕获),这是一个捕获错误调用的确切示例

但我认为这不是除了编写调试器之外的方式:

{-# LANGUAGE ScopedTypeVariables #-}
import Prelude hiding (catch)
import Control.Exception

setA :: Integer -> Integer
setA 3 = 5
setA 5 = 6
setA 7 = error "some error one"
setA _ = error "some error two"

main = do
  (print $ setA 9)
  `catch` (\(ErrorCall msg) -> putStrLn $ "I caught you, ErrorCall: " ++ msg)
  `catch` (\(exc::SomeException) -> putStrLn $ "Other exception: " ++ show exc)

对于正常编程,使用 type 包装可能的错误结果Either,正如其他答案所解释的那样。

于 2013-05-01T11:37:36.330 回答