gpt4 book ai didi

Haskell:为什么 Maybe 和 Either 类型用作 Monad 时表现不同?

转载 作者:行者123 更新时间:2023-12-01 22:56:52 24 4
gpt4 key购买 nike

我正在尝试了解 Haskell 中的错误处理。我找到了文章“8 ways to report errors in Haskell”,但我很困惑为什么 Maybe 和 Either 的行为不同。

例如:

import Control.Monad.Error

myDiv :: (Monad m) => Float -> Float -> m Float
myDiv x 0 = fail "My divison by zero"
myDiv x y = return (x / y)

testMyDiv1 :: Float -> Float -> String
testMyDiv1 x y =
case myDiv x y of
Left e -> e
Right r -> show r

testMyDiv2 :: Float -> Float -> String
testMyDiv2 x y =
case myDiv x y of
Nothing -> "An error"
Just r -> show r

调用 testMyDiv2 1 0 给出的结果是“An error”,但是调用 testMyDiv1 1 0 给出:

"*** Exception: My divison by zero

(请注意缺少结束引号,表明这不是字符串而是一个异常(exception))。

什么给出了?

最佳答案

简短的回答是,Haskell 中的 Monad 类在 monad 的原始数学思想中添加了 fail 操作,这使得如何将 Either 类型变成 (Haskell) >Monad,因为有很多方法可以做到这一点。

有几种实现不同的功能。我所知道的 3 种基本方法是:

  • 失败=左。这似乎是大多数人所期望的,但实际上在严格的 Haskell 98 中是无法完成的。该实例必须声明为 instance Monad (Either String),这在 H98 下是不合法的因为它提到了其中一个参数的特定类型(在 GHC 中,FlexibleInstances 扩展将使编译器接受它)。
  • 忽略fail,使用仅调用error的默认实现。这就是您的示例中发生的情况。该版本的优点是兼容 H98,但缺点是让用户感到相当惊讶(惊喜是在运行时出现的)。
  • fail 实现调用其他一些类将字符串转换为任何类型。这是在 MTL 的 Control.Monad.Error 模块中完成的,该模块声明 instance Error e => Monad (Either e)。在此实现中,fail msg = Left (strMsg msg)。这又是合法的 H98,并且偶尔也会让用户感到惊讶,因为它引入了另一种类型类别。与最后一个示例相反,令人惊讶的是在编译时。

关于Haskell:为什么 Maybe 和 Either 类型用作 Monad 时表现不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3795561/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com