函数monad真的能提供比函数应用函子更多的东西吗?如果是这样,是什么?

对于函数 monad,我发现(<*>)(>>=)/(=<<)有两个非常相似的类型。特别是,(=<<)使相似性更加明显:

(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
(=<<) :: (a -> r -> b) -> (r -> a) -> (r -> b)

所以它就像(<*>)(>>=)/(=<<)取一个二元函数和一个一元函数,并限制前者的两个参数之一通过后者从另一个参数中确定。毕竟,我们知道对于函数 applicative/monad,

f <*> g = x -> f x (g x)
f =<< g = x -> f (g x) x 

它们看起来非常相似(或者对称,如果你愿意的话),我不禁想到标题中的问题。

关于 monad 比应用函子“更强大”,在LYAH 的For a few Monads More章节的硬拷贝中,声明如下:

[...]join不能仅使用函子和应用程序提供的函数来实现。

join不能在以下方面来实现(<*>)purefmap

但是我上面提到的 applicative/mondad函数呢?

我知道,join === (>>= id)对于归结为 的函数 monad f x -> f x x,即通过将后者的一个参数作为前者的两个参数提供,使二元函数成为一元函数。

我可以用 来表达(<*>)吗?好吧,实际上我认为我可以:对flip ($) <*> f === join f吗?不是flip ($) <*> f的实现join它确实没有(>>=)/(=<<)return

然而,想着列表应用性/单子,我可以表达join不明确使用(=<<)/(>>=)return(甚至没有(<*>),FWIW)join = concat; 所以可能这个实现join f = flip ($) <*> f也是一种技巧,它并没有真正显示出我是仅仅依赖Applicative还是也依赖Monad.

回答

当你这样实现时join,你使用的函数类型知识超出Applicative了你的知识范围。这些知识在使用中编码($)。那就是“应用程序”运算符,它甚至是函数的核心。同样的事情发生在您的列表示例中:您正在使用concat,这是基于对列表性质的了解。

一般而言,如果您可以使用特定 monad 的知识,则可以表达任何幂的计算。例如,Maybe您可以匹配其构造函数并以这种方式表达任何内容。当 LYAH 说 monad 比 applicative 更强大时,它的意思是“作为抽象”,不适用于任何特定的 monad。

  • @Enlico `id` is a function. `(<*> id)` is not a polymorphic function that can be used with any applicative. Similarly, only for functions `(>>= id)` and `(id >>=)` are the same.

以上是函数monad真的能提供比函数应用函子更多的东西吗?如果是这样,是什么?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>