对于函数 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.