Haskell 为什么pointfree.io选择liftM2而不是liftA2?

Haskell 为什么pointfree.io选择liftM2而不是liftA2?,haskell,monads,functor,applicative,Haskell,Monads,Functor,Applicative,我最近正在为上的练习编写解决方案,当我运行此函数时: 我回来了: liftM2 (||) isDigit ('X' ==) 为什么pointfree.io从Control.Monad选择liftM2而不是Control.Applicative中选择liftA2?事实上Control.Monad比Control.Applicative旧得多 单子已经出现在Haskell 98中,而关于应用函子的论文是在2007年发表的。Hackage中的包自2005年以来就存在 : 由于历史的偶然性,应用程序函

我最近正在为上的练习编写解决方案,当我运行此函数时:

我回来了:

liftM2 (||) isDigit ('X' ==)

为什么pointfree.io从
Control.Monad
选择
liftM2
而不是
Control.Applicative
中选择
liftA2

事实上
Control.Monad
Control.Applicative
旧得多

单子已经出现在Haskell 98中,而关于应用函子的论文是在2007年发表的。Hackage中的包自2005年以来就存在

:

由于历史的偶然性,应用程序函子并没有作为Monad的超类实现,而是作为一个单独的类型类实现。事实证明,在实践中,这种分离的需求非常少,因此在2014年,有人提议将Applicative追溯为Monad的一个超类


所以
liftM{N}
仍然有效。

pointfree.io
是一个有趣的玩具,没有别的。它不应该以任何方式被期望提供好的建议,它只是暗示什么是可能的。我很惊讶它选择了
('X'==)
,而不是
(='X')
。显然,这种转换是“安全的”,因为
(==)
应该是对称的,但为什么它不选择一个精确的转换呢?@amalloy我无法回答为什么该工具会这样做,但我在编写部分应用程序时会注意到这一点。根据经验,首先应用较早的参数会更好,因为仔细编写的函数在给定其第一个参数时可能比在lambda下丢弃时共享更多的计算。e、 想象一下,如果
(==)
首先比较了关于每个参数的一些昂贵的统计数据,然后继续进行其他一些比较;然后
map(foo==)bar
可能比
map(=foo)bar
更有效,因为前者只计算了
foo
的统计信息一次。这个答案完全正确。也许值得注意的是,维基百科的解释相当奇怪:“几乎没有人要求这样的分离”听起来像是委婉语,因为这种分离没有任何意义。@duplode,我认为这种解释听起来是错误的,因为
应用性
总是(据我所知)
函子的子类。它肯定是由
base-4.0.0.0
在2009年推出的。@dfeuer哦,哇,这完全是错误的。(我没有意识到佩奇也在谈论
Functor
,这是由于深夜发帖和希望看到关于AMP的常见评论的结合。)@duplode,在检查了所有古老的文档以验证
Applicative
base-4.0.0.0
引入以来一直是
Functor
的一个子类之后,我编辑了Wikipedia以消除非常明确的错误。我想有人看到了原始论文中延伸出来的
Applicative
类缺少了
Functor
超类,因此感到困惑。@dfeuer这次对话提醒了我那篇文章的第一段。我已经做了一个很快的尝试,如果没有别的事情的话,我会让它变得正确。
liftM2 (||) isDigit ('X' ==)