简体   繁体   English

使用镜头在阵列上映射柯里化函数

[英]Map a curried function over an array using lenses

I have an object and want to update each value in an array inside of the object using some other object member.我有一个对象,想使用其他对象成员更新对象内部数组中的每个值。 Here is what I am attempting:这是我正在尝试的内容:

import * as R from 'ramda'

const obj = {
    array: [ 1, 2, 3 ],
    incrementBy: 0
};

const doIncrement = R.curry((inc,val) => {
    return val+inc;
});

const incrementLens = R.lensProp('incrementBy');
const setIncrementToOne = R.set(incrementLens,1);

const newObj = setIncrementToOne(obj);

const arrayLens = R.lensProp('array');

const incrementA = R.over(arrayLens, R.map(doIncrement(1)));

const incrementB = R.pipe(
    setIncrementToOne,
    R.chain(
        R.over(arrayLens, R.map(doIncrement)),
        R.view(incrementLens)
    )
)

console.log(JSON.stringify(incrementA(newObj))); // works: {"array":[2,3,4],"incrementBy":1}
console.log(JSON.stringify(incrementB(obj))); // does not work (TypeError: Cannot read property 'fantasy-land/map' of undefined)

Version A obviously works as I access the array directly and map my curried function over it.当我直接访问数组并将我的柯里化函数映射到它时,版本 A 显然有效。 In version B, however, I am unsure of the order of things;然而,在版本 B 中,我不确定事情的顺序; what I've tried now does not appear to pass the value from R.view to the curried function appropriately.我现在尝试过的似乎没有将值从R.view适当地传递给R.view函数。

(NB. that the use case is more complex, I would just like to understand how I can work with curried functions, maps and lenses simultaneously.) (注意,用例更复杂,我只想了解如何同时使用柯里化函数、地图和镜头。)

When R.chain is applied to functions - chain(f, g)(x) is equivalent to f(g(x))(x) - applying function g on value 'x', returning, and then applying function f on the result of g(x) and then on value x .R.chain被施加到功能- chain(f, g)(x)相当于f(g(x))(x) -赋予功能g上值的'x',返回,然后应用功能fg(x)结果,然后是值x

In your case:在你的情况下:

  • g(x) ( R.view(incrementLens) ) is 1 g(x) ( R.view(incrementLens) ) 是 1
  • f ( R.over(arrayLens, R.map(doIncrement)) ) is a function that waits for the value (not another function) f ( R.over(arrayLens, R.map(doIncrement)) ) 是一个等待值的函数(不是另一个函数)

Applying f ( R.over... ) on g(x) applies a lens on a non object value, and even if it was an object the result would have been another value, which means that you don't have a function to apply to on the result of setIncrementToOne in the pipe.g(x) ) 上应用f ( R.over... ) 将透镜应用于非对象值,即使它是一个对象,结果也会是另一个值,这意味着您没有函数应用于管道中setIncrementToOne的结果。

The result of g(x) in this case needs to be a function, that can be used by R.over with the arraylens - to get the R.over(arrayLens, R.map(R.add(1))) , which is identical to incrementA .的结果g(x)在这种情况下需要是一个功能,即可以通过使用R.overarraylens -获得R.over(arrayLens, R.map(R.add(1)))这与incrementA相同。

Note: I've replaced doIncrement with R.add , which does the same thing.注意:我已经用doIncrement替换了R.add ,它做同样的事情。

 const obj = { array: [1, 2, 3], incrementBy: 0 }; const incrementLens = R.lensProp('incrementBy'); const setIncrementToOne = R.set(incrementLens, 1); const newObj = setIncrementToOne(obj); const arrayLens = R.lensProp('array'); const incrementB = R.pipe( setIncrementToOne, R.chain( R.over(arrayLens), R.pipe(R.view(incrementLens), R.add, R.map) ) ) const incrementA = R.over(arrayLens, R.map(R.add(1))); console.log(JSON.stringify(incrementA(newObj))); // works: {"array":[2,3,4],"incrementBy":1} console.log(JSON.stringify(incrementB(obj))); // works: {"array":[2,3,4],"incrementBy":1}
 <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM