R.head如何成为'链'的类型

问题描述 投票:0回答:1

我想了解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类型兼容的有效输入以及我们所做的其余公式操作?

javascript functional-programming ramda.js
1个回答
1
投票

从这里开始:

chain ::(a - >(x - > b)) - >(x - > a) - >(x - > b)

你似乎已经理解了,在这里我们将m b解释为“一个需要x并返回b的函数”。因此,m a将是“一个接受x并返回a的函数”。

将这与concat的签名并排比较(我将使用y以避免在不同的x之间产生混淆):

(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-able,当以下都是真的:

  • g(x)f的第一个参数具有相同的类型
  • f的第二个参数与g的第一个参数具有相同的类型
© www.soinside.com 2019 - 2024. All rights reserved.