应用程序组成,单子不 [英] Applicatives compose, monads don't

查看:19
本文介绍了应用程序组成,单子不的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

应用程序组成,monads 没有.

Applicatives compose, monads don't.

上面的说法是什么意思?什么时候一个比另一个更可取?

What does the above statement mean? And when is one preferable to other?

推荐答案

如果我们比较类型

(<*>) :: Applicative a => a (s -> t) -> a s -> a t
(>>=) :: Monad m =>       m s -> (s -> m t) -> m t

我们得到了区分这两个概念的线索.(>>=) 类型中的 (s -> mt) 表明 s 中的值可以决定行为mt 中的计算.Monads 允许值层和计算层之间的干扰.(<*>) 运算符不允许这种干扰:函数和参数计算不依赖于值.这真的很咬人.比较

we get a clue to what separates the two concepts. That (s -> m t) in the type of (>>=) shows that a value in s can determine the behaviour of a computation in m t. Monads allow interference between the value and computation layers. The (<*>) operator allows no such interference: the function and argument computations don't depend on values. This really bites. Compare

miffy :: Monad m => m Bool -> m x -> m x -> m x
miffy mb mt mf = do
  b <- mb
  if b then mt else mf

它使用某种效果的结果来决定两个计算(例如发射导弹和签署停战协定),而

which uses the result of some effect to decide between two computations (e.g. launching missiles and signing an armistice), whereas

iffy :: Applicative a => a Bool -> a x -> a x -> a x
iffy ab at af = pure cond <*> ab <*> at <*> af where
  cond b t f = if b then t else f

它使用ab的值在两个计算ataf的值之间进行选择,有两者都进行了,也许会导致悲剧性的结果.

which uses the value of ab to choose between the values of two computations at and af, having carried out both, perhaps to tragic effect.

monadic 版本本质上依赖于 (>>=) 的额外功能来从一个值中选择一个计算,这很重要.然而,支持这种能力使得 monad 难以组合.如果我们尝试构建双重绑定"

The monadic version relies essentially on the extra power of (>>=) to choose a computation from a value, and that can be important. However, supporting that power makes monads hard to compose. If we try to build ‘double-bind’

(>>>>==) :: (Monad m, Monad n) => m (n s) -> (s -> m (n t)) -> m (n t)
mns >>>>== f = mns >>-{-m-}  ns -> let nmnt = ns >>= (return . f) in ???

我们已经走到了这一步,但现在我们的层都乱七八糟了.我们有一个n (m (n t)),所以我们需要去掉外面的n.正如 Alexandre C 所说,如果我们有合适的

we get this far, but now our layers are all jumbled up. We have an n (m (n t)), so we need to get rid of the outer n. As Alexandre C says, we can do that if we have a suitable

swap :: n (m t) -> m (n t)

向内置换 n 并将其 join 到另一个 n.

to permute the n inwards and join it to the other n.

较弱的双重申请";更容易定义

The weaker ‘double-apply’ is much easier to define

(<<**>>) :: (Applicative a, Applicative b) => a (b (s -> t)) -> a (b s) -> a (b t)
abf <<**>> abs = pure (<*>) <*> abf <*> abs

因为层与层之间没有干扰.

because there is no interference between the layers.

相应地,当您真正需要 Monad 的额外功能时,以及何时可以摆脱 Applicative 支持的刚性计算结构时,最好认识到.

Correspondingly, it's good to recognize when you really need the extra power of Monads, and when you can get away with the rigid computation structure that Applicative supports.

顺便说一下,尽管组合 monad 很困难,但它可能比您需要的更多.m (nv) 类型表示用 m-effects 计算,然后用 n-effects 计算到 v-value,其中 m-effects 在 n-effects 开始之前完成(因此需要 swap).如果你只是想将 m-effects 与 n-effects 交错,那么组合可能要求太多了!

Note, by the way, that although composing monads is difficult, it might be more than you need. The type m (n v) indicates computing with m-effects, then computing with n-effects to a v-value, where the m-effects finish before the n-effects start (hence the need for swap). If you just want to interleave m-effects with n-effects, then composition is perhaps too much to ask!

这篇关于应用程序组成,单子不的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆