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)
它看起来像一个非常有用的功能.我看不出它会是什么用例.
谢谢
这个函数只能接受数字:
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)
函数式编程是一个长期的数学主题,特别是处理 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。
也许你从这一点开始失去兴趣......但是我们之前有人对这个话题迷失了,最后他活了下来并发表了它作为这个问题的答案。
让我们看看他看到了什么……
...
他看到了幻想乡
在幻想世界中,一个对象
Apply在ap定义了一个方法时实现了规范(该对象也必须Functor通过定义一个map方法来实现 规范)。
所以,等等……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 中,这用于包装不安全的操作,例如输入/输出。它也可以是错误包装器或树,甚至是任何数据结构。
| 归档时间: |
|
| 查看次数: |
199 次 |
| 最近记录: |