首页 > 解决方案 > 函数单子真的提供了比函数应用函子更多的东西吗?如果是这样,是什么?

问题描述

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

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

因此,就像(<*>)and (>>=)/(=<<)采用二元函数和一元函数,并通过后者约束前者的两个参数之一与另一个参数确定。毕竟,我们知道对于函数 applicative/monad,

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

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

至于 monad 比 applicative functors “更强大”,在LYAH 的For a Few Monads More章节的硬拷贝中,陈述如下:

[…]join不能仅通过使用仿函数和应用程序提供的功能来实现。

join不能用(<*>),pure和来实现fmap

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

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

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

但是,考虑到列表 applicative/monad,我可以join在不显式使用(=<<)/(>>=)return(甚至不是(<*>),fwiw)的情况下表达join = concat:所以可能实现join f = flip ($) <*> f也是一种技巧,并没有真正表明我是依赖Applicative还是依赖Monad.

标签: haskellfunctional-programmingmonadsapplicativecombinatory-logic

解决方案


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

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


推荐阅读