首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Monads和liftM

Monads和liftM
EN

Stack Overflow用户
提问于 2020-01-24 15:32:20
回答 3查看 181关注 0票数 1

我在使用liftM时遇到了问题。对于(+),它工作得很好,madd a b = liftM2 (+) a b函数给了我预期的结果Just 5 `madd` Just 7 = Just 12,但是现在用(/)尝试它,它给了我奇怪的结果。

现在,操作Just 12 `mdiv` Just 0给了我Just Infinity,而我期待的是Nothing

EN

回答 3

Stack Overflow用户

发布于 2020-01-24 17:08:33

Monad不是魔术,它们只是封装了特定的计算模式。

代码语言:javascript
复制
liftM2 :: Monad m => (a -> b -> c) -> m a -> m b -> m c

以及Maybe monad的特定版本,

代码语言:javascript
复制
liftM2 :: (a -> b -> c) -> Maybe a -> Maybe b -> Maybe c

这里没有关于数字和除以零的错误。这里我们所知道的是一元值是Just something还是Nothing

这允许我们定义一个安全的除法函数,但它不会单独为我们做这件事。

Haskell不是一个智能的编写代码的AI代理。这只是另一种编程语言,程序员而不是计算机来编写程序。此外,为什么要由它来决定您是否希望发生运行时被零除的错误!

票数 9
EN

Stack Overflow用户

发布于 2020-01-24 16:59:59

如果你启动GHCi并尝试‘裸体’除法运算,你会得到Infinity

代码语言:javascript
复制
Prelude> 12 / 0
Infinity

liftM2只允许您在一元上下文中执行操作。在Just 12Just 0的情况下,该上下文是Maybe。它不会改变操作;它只是处理容器引入的可变性。

代码语言:javascript
复制
Prelude Control.Monad> liftM2 (/) (Just 12) (Just 0)
Just Infinity
Prelude Control.Monad> liftM2 (/) (Just 12) Nothing
Nothing
Prelude Control.Monad> liftM2 (/) Nothing (Just 0)
Nothing
Prelude Control.Monad> liftM2 (/) (Just 12) (Just 3)
Just 4.0
Prelude Control.Monad> liftM2 (/) Nothing Nothing
Nothing

注意当其中一个或两个参数都为Nothing时,liftM2是如何处理的。如果没有恰好两个值,则不能调用带有两个参数(如/+)的函数。liftM2通过返回Nothing来处理值少于两个的情况。

另一方面,如果恰好有两个值,它就会调用函数。当您使用Just 12Just 0调用它时,您确实有两个值,并且/操作被调用,从而产生Infinity

这和预期的一样。

票数 3
EN

Stack Overflow用户

发布于 2020-01-24 22:02:43

其他答案已经指出了为什么这种方式适用于Maybe monad。但当然,Maybe并不是唯一的monad。您希望这也适用于IO、解析器和所有其他monads:

代码语言:javascript
复制
foo :: IO Double
foo = liftM2 (/) (return 12) (return 0)

foo应该返回什么?它不能是Nothing,因为它不在Maybe monad中。

您可以使用fail,在Maybe monad中,它的计算结果为Nothing,更常见的情况是计算为某种异常值,或者根据monad调用error

当然,在12 / 0的特殊情况下,正确的答案实际上是Infinity。定义IEEE754标准的数字专家这样做是有原因的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59892147

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档