R.head 怎么可能是 'chain a' 类型
How can R.head be of type 'chain a'
我正在努力理解buzzdecafe's Chain chain chain article
那篇文章解释了如何使用 R.chain 将数组中的第一个值附加到该数组的(末尾),以及这样做的原因。
const f = chain(append, head); //=> f :: [x] -> [x]`
f([1, 2, 3]); //=> [1, 2, 3, 1]
在倒数第五段他写道
head is of type 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
可以是 returns x 类型的函数吗?好吗?但是那个函数的输入呢?我如何才能看到并理解 [x]
将是与 R.chain 类型兼容的有效输入以及我们所做的 公式操作 的其余部分?
从这里开始:
chain :: (a -> (x -> b)) -> (x -> a) -> (x -> b)
看来你已经明白了,这里我们将m b
解释为"a function that takes an x
and returns a b
"。因此 m a
将是 "a function that takes an x
and returns an a
".
将此与 concat
的签名并排比较(我将使用 y
以避免不同 x
es 之间的混淆):
(a -> (x -> b))
y -> [y]-> [y]
我们可以看出a
是y
,x
是[y]
,b
也是[y]
。因此,采用 x
和 returns 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])
这有助于清除它吗?
另一种看待这个问题的方法是,如果 f
和 g
都是函数,那么:
chain(f, g)(x) is equivalent to f(g(x), x)
这几乎就是我们在 Ramda source:
中看到的内容
fn(monad(x))(x)
从这里,我们可以看出函数 f
和 g
是 chain
-able 当以下条件都为真时:
g(x)
与f
的第一个参数类型相同
f
的第二个参数与g
的第一个参数具有相同的类型
我正在努力理解buzzdecafe's Chain chain chain article
那篇文章解释了如何使用 R.chain 将数组中的第一个值附加到该数组的(末尾),以及这样做的原因。
const f = chain(append, head); //=> f :: [x] -> [x]`
f([1, 2, 3]); //=> [1, 2, 3, 1]
在倒数第五段他写道
head is of type 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
可以是 returns x 类型的函数吗?好吗?但是那个函数的输入呢?我如何才能看到并理解 [x]
将是与 R.chain 类型兼容的有效输入以及我们所做的 公式操作 的其余部分?
从这里开始:
chain :: (a -> (x -> b)) -> (x -> a) -> (x -> b)
看来你已经明白了,这里我们将m b
解释为"a function that takes an x
and returns a b
"。因此 m a
将是 "a function that takes an x
and returns an a
".
将此与 concat
的签名并排比较(我将使用 y
以避免不同 x
es 之间的混淆):
(a -> (x -> b))
y -> [y]-> [y]
我们可以看出a
是y
,x
是[y]
,b
也是[y]
。因此,采用 x
和 returns 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])
这有助于清除它吗?
另一种看待这个问题的方法是,如果 f
和 g
都是函数,那么:
chain(f, g)(x) is equivalent to f(g(x), x)
这几乎就是我们在 Ramda source:
中看到的内容fn(monad(x))(x)
从这里,我们可以看出函数 f
和 g
是 chain
-able 当以下条件都为真时:
g(x)
与f
的第一个参数类型相同
f
的第二个参数与g
的第一个参数具有相同的类型