haskell - Haskell 异常的含义

标签 haskell

Haskell中异常的含义是什么?我看到的唯一用法是输入 undefinederror在我的代码中阻止程序运行。否则,我将异常编程视为逻辑设计缺陷。但是 Haskell 有一个高级异常模块 Control.ExceptionPrelude 使用.我读到 C++ 中出现异常的原因是为了防止代码中出现大量“调用函数,然后检查状态”行。但是这些东西可以在 Haskell 中抽象出来。我可以看到在 Haskell 中进行异常处理的唯一其他原因是使用 FFI 来处理外部异常,但仅用于包装调用的 Haskell 函数的内部使用。

最佳答案

在我看来,异常(exception)意味着“你违反了函数的契约(Contract)”。我不是在谈论类型契约(Contract),而是在谈论您通常在评论中找到的东西。

-- The reciprocal is not defined for the value 0
myRecip :: Fractional a => a -> a
myRecip x | x == 0    = throw DivideByZero
          | otherwise = 1 / x

当然,您始终可以以“安全”的方式提供此功能:
safeRecip :: Fractional a => a -> Maybe a
safeRecip x | x == 0    = Nothing
            | otherwise = Just $ 1 / x

或许我们甚至应该抽象出这种模式
restrictInput :: (a -> Bool) -> (a -> b) -> (a -> Maybe b)
restrictInput pred f x = if pred x then Just (f x) else Nothing

safeRecip' = restrictInput (/= 0) myRecip

您可以想象使用 Either 的类似组合子。而不是 Maybe报告失败。那么既然我们有能力用纯函数处理这些事情,为什么还要为不纯的异常模型烦恼呢?好吧,大多数 Haskeller 会告诉你要坚持纯洁。但黑暗的事实是,添加额外的层只是一种痛苦。你不能再写了
prop_recip x = x == (recip . recip) x

因为现在 recip x 的结果位于 Maybe .您可以使用 (a -> a) 做一些有用的事情你不能再做的功能。现在你必须考虑创作Maybes。当然,如果您对 monad 感到满意,这将是微不足道的:
prop_recip 0 = (safeRecip >=> safeRecip) 0 == Nothing
prop_recip x = (safeRecip >=> safeRecip) x == Just x

但问题就在这里。当涉及到一元组合时,新手通常几乎一无所知。 Haskell 委员会,正如#haskell irc channel 上的许多人会很快告诉你的那样*,为了迎合新手,在语言设计方面做出了一些相当不稳定的决定。我们希望能够说“你不需要知道 monad 就可以开始在 Haskell 中制作有用的东西”。我大体上同意这种观点。

tl;博士
对这个问题的一些快速回答:什么是异常(exception)?
  • 一个肮脏的黑客,所以我们不必让我们的功能完全安全
  • IO monad 的“try/catch”控制流机制(IO 是一个 sin bin,那么为什么不把 try/catch 也扔到 sins 列表中呢?)

  • 可能还有其他解释。

    另见 Haskell Report > Basic Input/Output > Exception Handling in the IO Monad

    *我实际上在#haskell irc 上问过他们是否同意这一声明。我得到的唯一回复是"wonky" :)因此,没有异议显然证明了它是正确的。

    [编辑] 注意 errorundefined根据 throw 定义:
    error :: [Char] -> a
    error s = throw (ErrorCall s)
    
    undefined :: a
    undefined =  error "Prelude.undefined"
    

    关于haskell - Haskell 异常的含义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7704999/

    相关文章:

    Haskell:是否存在任何类型的对象,例如 Java 中的 `null`?

    haskell - 有没有一种很好的方法可以让 Haskell 中的函数签名提供更多信息?

    haskell - Markup monad 与 Html monad 是如何关联的?

    haskell - 惰性求值如何与 MVar 相互作用?

    haskell - 在第一次出现 x 之前插入元素 y 的函数?

    haskell - 在 Haskell 中创建 UArray Int(复数 double )

    haskell - marshaller 中的 c2hs 与 gtk2hsC2hs

    haskell - curry 语言的 CPS

    c - 哪些绿色线程库可用于 C,可以匹配 Haskell 绿色线程的性能和易用性?

    haskell - 编译器优化(例如 ghc -O2)可以更改程序的顺序(时间或存储)吗?