haskell - liftM 函数是否被剥夺了它们的一元本质?

标签 haskell functional-programming monads applicative lifting

monad 和 applicative 的区别在于前者可以根据之前的结果选择下一个计算:

(\x -> if x == 1 then (\_ -> []) else (\y -> (\z -> \w -> [x,y,z]) =<< sqr) =<< (+1)) =<< (+1) $ 0
--                      ^

(\w x -> if x == 1 then (\_ _ -> []) else (\y z -> [x,y,z])) <*> (+1) <*> (+1) <*> sqr $ 0
--                        ^^^

monadic 计算可以使计算短路,而对于 applicative 计算,我们必须使用整个计算结构并运行所有效果,无论我们提供什么输入。

让我们将其与 liftM 进行比较:
liftM3 (\x -> if x == 1 then (\_ _ -> []) else (\y z -> [x,y,z])) (+1) (+1) sqr $ 0
--                             ^^^

这似乎是变相的应用风格。即使我用一元涂抹器替换升降机操作符,整个结构似乎也失去了它的一元属性:
appM3 w f x g y h z =
  f(\x' -> g(\y' -> h(\z' -> w x' y' z') z) y) x

appM3 (\x -> if x == 1 then (\_ _ _ -> []) else (\y z _ -> [x, y, z])) (=<<) (+1) (=<<) (+1) (=<<) sqr $ 0
--                            ^^^^^

这是否意味着必须始终手动编码适当的一元计算?我知道 do 表示法,但底层机制似乎类似于宏扩展(如果这是废话,请纠正我),所以它并不能真正反驳我的假设。

最佳答案

你是对的。 liftM只是 fmap , 和 liftM2只是 liftA2 .它们的存在是标准库中仍然僵化的历史产物,而不是实际需要单子(monad)绑定(bind)操作的力量的东西。

以前版本的标准库没有使 FunctorApplicative Monad 的父类(super class). (如果你回溯到足够远,Applicative 甚至都不存在。)因此,为了实用性,创建了执行相同操作的函数以与 Monad 一起使用。 .它们在 Applicative-Monad 提案的过渡中幸存下来,因为它们对一个目的仍然有用 - 如果您手动实现所有类,则可以使用它们来实现类型的 FunctorApplicative Monad 方面的实例代码。

关于haskell - liftM 函数是否被剥夺了它们的一元本质?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60197622/

相关文章:

Scala:如何从 Set[K] 创建 Map[K,V] 和从 K 到 V 的函数?

javascript - 如何将此JavaScript代码转换为功能方式(最好使用Ramdajs)?

haskell - 是否有一个直接的解决方案来接收元素 *prior* 击中 dropWhile 谓词?

scala - 如何将选项转换为无?

haskell - Functor -> Applicative -> Monad 层次结构的意义是什么

macos - ghc 动态库中的_closure 和_info 符号

haskell - 堆栈安装错误: Recommended extra-dep

Haskell——有什么方法可以关闭 `deriving` 实例的可重新绑定(bind)语法?

Haskell:了解 Monad 的绑定(bind)运算符 (>>=)

javascript - 单子(monad)组合练习错误