我试图了解buzzdecafe's Chain chain chain article

那篇文章解释了如何使用R.chain将数组中的第一个值附加到该数组的(末尾),以及为什么这样做。

const f = chain(append, head); //=> f :: [x] -> [x]`
f([1, 2, 3]); //=> [1, 2, 3, 1]


在最后第五段中,他写道


  头是m a型


作为刚开始尝试函数式编程的人,我对此一无所知。

我不完全理解文章中从数组到函数以及从数组到函数的不同类型链所进行的替换。

R.chain的类型是:

(a -> m b)          ->  m a       ->  m b


我知道一条链可以是一个功能。因此,具有类型x → [x] → [x]的R.append可以重写为a -> m b并且适合R.chain类型的第一部分。我认为那意味着我们现在已经定义了(或任何词)m b[x] -> [x],因此最后一个m b也必须替换为[x] -> [x]吗?

在这种情况下,我们所拥有的将如下所示:

(a -> [x] -> [x])   ->  m a       ->  ([x] -> [x])


由于a和x的类型相同(在这种情况下为数字),所以我们有:

(x -> [x] -> [x])   ->  m x       ->  ([x] -> [x])


因此第一个过去匹配R.append。最后匹配返回函数的类型。太好了,我有点理解...

但是...之间的m x如何适合R.head? m x可以是返回类型x的函数吗?好?但是该功能的输入呢?我如何看到并理解[x]是与R.chain的类型以及我们所做的其余公式操作兼容的有效输入?

最佳答案

从这开始:


  链条::(a->(x-> b))->(x-> a)->(x-> b)


似乎您已经了解了,这里我们将m b解释为“一个带有x并返回b的函数”。因此,m a将成为“接受x并返回a的函数”。

将这与concat的签名进行比较(我将使用y以避免不同的x es之间的混淆):

(a -> (x -> b))
 y -> [y]-> [y]


我们可以看到ayx[y],并且b也是[y]。因此,采用x并返回a的函数将具有签名[y] -> y,恰好是head具有的签名。

因此,我们最后得到的是:

append                    head
 a ->    m b                m a              m b
 a ->  x  ->  b     ->  ( x  -> a)   ->  ( x  ->  b )
(y -> [y] -> [y])   ->  ([y] -> y)   ->  ([y] -> [y])


这有助于清除它吗?

另一种查看方式是,如果fg都是函数,则:

chain(f, g)(x)  is equivalent to   f(g(x), x)


这几乎是我们在Ramda source中看到的:

fn(monad(x))(x)


由此可见,当满足以下两个条件时,函数fgchain可用的:


g(x)f的第一个参数具有相同的类型
f的第二个参数与g的第一个参数具有相同的类型

关于javascript - R.head如何成为“chain a”类型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47970718/

10-12 12:35
查看更多