你能给我一个如何使用Ramda电梯的例子吗?

Ada*_*dam 6 javascript functional-programming ramda.js

我正在阅读ramda文档

const madd3 = R.lift((a, b, c) => a + b + c);

madd3([1,2,3], [1,2,3], [1]); //=> [3, 4, 5, 4, 5, 6, 5, 6, 7]
Run Code Online (Sandbox Code Playgroud)

它看起来像一个非常有用的功能.我看不出它会是什么用例.

谢谢

cus*_*der 6

这个函数只能接受数字:

const add3 = (a, b, c) => a + b + c;
add3(1, 2, 3); //=> 6
Run Code Online (Sandbox Code Playgroud)

但是,如果这些数字都包含在一个函子中呢?(即包含值的事物;下例中的数组)

add3([1], [2], [3]); //=> "123"
Run Code Online (Sandbox Code Playgroud)

这显然不是我们想要的。您可以“提升”函数,以便它可以“提取”每个参数/函子的值:

const add3Lifted = lift(add3);
add3Lifted([1], [2], [3]); //=> [6]
Run Code Online (Sandbox Code Playgroud)

数组显然可以保存多个值,并结合一个知道如何提取每个函子值的提升函数,你现在可以这样做:

add3Lifted([1, 10], [2, 20], [3, 30]);
//=> [6, 33, 24, 51, 15, 42, 33, 60]
Run Code Online (Sandbox Code Playgroud)

如果你这样做了,这基本上就是你所得到的:

[
  add3(1, 2, 3),    // 6
  add3(1, 2, 30),   // 33
  add3(1, 20, 3),   // 24
  add3(1, 20, 30),  // 51
  add3(10, 2, 3),   // 15
  add3(10, 2, 30),  // 42
  add3(10, 20, 3),  // 33
  add3(10, 20, 30)  // 60
]
Run Code Online (Sandbox Code Playgroud)

请注意,每个数组不必具有相同的长度:

add3Lifted([1, 10], [2], [3]);
//=> [6, 15]
Run Code Online (Sandbox Code Playgroud)

所以要回答你的问题:如果你打算运行一个具有不同值集的函数,提升该函数可能是一个有用的考虑:

const results = [add3(1, 2, 3), add3(10, 2, 3)];
Run Code Online (Sandbox Code Playgroud)

是相同的:

const results = add3Lifted([1, 10], [2], [3]);
Run Code Online (Sandbox Code Playgroud)


Dav*_*mon 5

函数式编程是一个长期的数学主题,特别是处理 monads分类理论的部分。但值得一看,这里有一个带图片的有趣介绍

简而言之,lift 是一个函数,它将接受一个n-arguments函数,并将产生一个接受n 个 包裹值的函数,并产生另一个结果包裹值。采用单参数函数的提升由以下类型签名定义

 // name :: f is a wrp-value => function -> wrp-value -> wrp-value
 liftA :: Applicative f   => (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)

等等...包装值?

我将简要介绍一下 Haskell,只是为了说明这一点。在haskell中,一个简单的包裹值的例子是Maybe,Maybe可以是一个包裹值或什么都没有,那也是一个包裹值。以下示例将函数应用于包含值的 Maybe 和空的 Maybe 。

> liftA (+ 8) (Just 8)
Just 16
> liftA (+ 8) Nothing
Nothing
Run Code Online (Sandbox Code Playgroud)

该列表也是一个包装值,我们可以对其应用函数。在第二种情况下,liftA2 将双参数函数应用于两个列表。

> liftA (+ 8) [1,2,3]
[9,10,11]
> liftA2 (*) [1..3] [1..3]
[1,2,3,2,4,6,3,6,9]
Run Code Online (Sandbox Code Playgroud)

这个包装值是一个 Applicative Functor,所以从现在开始我将它称为 Applicative。

也许你从这一点开始失去兴趣......但是我们之前有人对这个话题迷失了,最后他活了下来并发表了它作为这个问题的答案

让我们看看他看到了什么……

...

你看见什么了? (xkcd漫画)

他看到了幻想乡

在幻想世界中,一个对象Applyap定义了一个方法时实现了规范(该对象也必须Functor通过定义一个map方法来实现 规范)。

  • Fantasy-land 是 JavaScript 函数式编程规范的一个奇特名称。拉姆达紧随其后。
  • Apply 是我们的 Applicative,一个实现了ap方法的 Functor
  • 函子,是什么,有地图的方法。

所以,等等……javascript 中的数组有一个映射……

[1,2,3].map((a)=>a+1) \\=> [ 2, 3, 4 ]
Run Code Online (Sandbox Code Playgroud)

那么 Array 是一个 Functor,并且 map 将一个函数应用于它的所有值,返回另一个具有相同数量值的 Functor。

但是ap 有什么作用呢?

ap 将函数列表应用于值列表。

调度到第二个参数的 ap 方法(如果存在)。还将咖喱函数视为应用程序。

让我们试着用它做点什么。

 // name :: f is a wrp-value => function -> wrp-value -> wrp-value
 liftA :: Applicative f   => (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
> liftA (+ 8) (Just 8)
Just 16
> liftA (+ 8) Nothing
Nothing
Run Code Online (Sandbox Code Playgroud)

ap 方法采用函数数组(或其他一些 Applicative)并将其应用于值的 Applicative 以生成另一个扁平化的 Applicative。

该方法的签名解释了这一点

[a ? b] ? [a] ? [b]
Apply f => f (a ? b) ? f a ? f b
Run Code Online (Sandbox Code Playgroud)

最后,lift有什么作用?

Lift 接受一个带有n 个参数的函数,并生成另一个接受n Aplicatives并生成结果的扁平化Aplicative的函数。

在这种情况下,我们的 Applicative 是数组。

> liftA (+ 8) [1,2,3]
[9,10,11]
> liftA2 (*) [1..3] [1..3]
[1,2,3,2,4,6,3,6,9]
Run Code Online (Sandbox Code Playgroud)
[1,2,3].map((a)=>a+1) \\=> [ 2, 3, 4 ]
Run Code Online (Sandbox Code Playgroud)

这些包装器(Applicatives、Functors、Monads)很有趣,因为它们可以是任何实现这些方法的东西。在haskell 中,这用于包装不安全的操作,例如输入/输出。它也可以是错误包装器或树,甚至是任何数据结构。