我正在努力提高对 Applicative
的理解s 和 Monad
s 通过在 Javascript 中实现它们的函数实例。我对 Haskell 的了解有限,我希望我的问题完全有道理。
这是我对 fmap
的实现, <*>
和 >>=
对于Functor
, Applicative
和 Monad
Javascript中的类型类:
const fmap = f => g => x => f(g(x)); // B combinator
const apply = f => g => x => f(x) (g(x)); // S combinator
const bind = f => g => x => g(f(x)) (x); // ?
我不确定
bind
是 Haskell 实现的正确翻译:(>>=) :: (r -> a) -> (a -> (r -> b)) -> r -> b
instance Monad ((->) r) where
f >>= k = \ r -> k (f r) r
前提是
bind
是正确的,它是如何解释的?我知道 Applicative
可以对有效的计算进行排序。我也知道Monad
此外,您还可以根据前一个效果的结果确定下一个效果。我可以看到序列(Javascript 中的急切评估顺序):
apply
: f(x)
... g(x)
... lambda(result of g)
... lambda
的结果bind
: f(x)
... g(result of f)
... lambda(x)
... lambda
的结果但是,
bind
功能看起来很奇怪。为什么是 f
和 g
反过来嵌套?具体如何Monad
此实现中反射(reflect)的行为(根据前一个效果确定下一个效果)?其实g(f(x)) (x)
看起来像一个带有翻转参数的函数组合,其中 g
是二元函数。当我申请
apply
/bind
使用一元和二元函数,它们产生相同的结果。这没有多大意义。
最佳答案
Lee's answer 的一些脚注:
However, the
bind
function looks pretty weird. Why aref
andg
nested the other way around?
因为
bind
是倒退的。比较 (>>=)
及其翻转版(=<<)
:(>>=) :: Monad m => m a -> (a -> m b) -> m b
(=<<) :: Monad m => (a -> m b) -> m a -> m b
或者,在您的具体示例中:
(>>=) :: (r -> a) -> (a -> (r -> b)) -> (r -> b)
(=<<) :: (a -> (r -> b)) -> (r -> a) -> (r -> b)
在实践中,我们倾向于使用
(>>=)
多于 (=<<)
(因为 (>>=)
,从语法上讲,它非常适合用于构建的管道单子(monad)),从理论的角度来看 (=<<)
是最自然的写法。特别是与 fmap
的异同。/(<$>)
和 (<*>)
更明显:(<$>) :: Functor f => (a -> b) -> f a -> f b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
(=<<) :: Monad f => (a -> f b) -> f a -> f b
When I apply
apply
/bind
with an unary and a binary function, they yield the same result. This doesn't make much sense.
这是关于函数实例的一个偶然事实。让我们并排放置专门的签名:
(<*>) :: (r -> (a -> b)) -> (r -> a) -> (r -> b)
(=<<) :: (a -> (r -> b)) -> (r -> a) -> (r -> b)
Monad
超越Applicative
通过提供根据先前结果确定下一个效果的方法(与“以前的效果”相反——Applicative
已经可以做到这一点)。在这种情况下,效果由一个函数组成,该函数在给定 r
类型的参数的情况下生成值。 .现在,由于可以翻转具有多个参数的函数(即返回函数的函数),因此 (r -> (a -> b))
之间没有显着差异。和 (a -> (r -> b))
(flip
可以很容易地将一个更改为另一个),这使得 Monad
(->) r
的实例完全等同于 Applicative
一。
关于haskell - 如何解释函数实例的bind/>>=?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40131562/