使用透镜将柯里化函数映射到数组上
Map a curried function over an array using lenses
我有一个对象,想使用其他对象成员更新对象内数组中的每个值。这是我正在尝试的:
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)
版本 A 显然有效,因为我直接访问数组并将我的柯里化函数映射到它上面。但是,在版本 B 中,我不确定事物的顺序;我现在尝试的方法似乎没有将值从 R.view
适当地传递给柯里化函数。
(注意,用例更复杂,我只想了解如何同时使用柯里化函数、贴图和镜头。)
当 R.chain
应用于函数时 - chain(f, g)(x)
等同于 f(g(x))(x)
- 在值 'x' 上应用函数 g
,返回,然后应用函数 f
在 g(x)
的结果上,然后在值 x
上。
你的情况:
g(x)
(R.view(incrementLens)
) 是 1
f
(R.over(arrayLens, R.map(doIncrement))
)是一个等待值的函数(不是另一个函数)
在 g(x)
上应用 f
(R.over...
) 在非对象值上应用透镜,即使它是一个对象,结果也会是另一个值,这意味着你没有一个函数可以应用于管道中 setIncrementToOne
的结果。
在这种情况下 g(x)
的结果需要是一个函数,它可以被 R.over
与 arraylens
一起使用 - 以获得 R.over(arrayLens, R.map(R.add(1)))
,它等同于 incrementA
.
注意:我已将 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>
我有一个对象,想使用其他对象成员更新对象内数组中的每个值。这是我正在尝试的:
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)
版本 A 显然有效,因为我直接访问数组并将我的柯里化函数映射到它上面。但是,在版本 B 中,我不确定事物的顺序;我现在尝试的方法似乎没有将值从 R.view
适当地传递给柯里化函数。
(注意,用例更复杂,我只想了解如何同时使用柯里化函数、贴图和镜头。)
当 R.chain
应用于函数时 - chain(f, g)(x)
等同于 f(g(x))(x)
- 在值 'x' 上应用函数 g
,返回,然后应用函数 f
在 g(x)
的结果上,然后在值 x
上。
你的情况:
g(x)
(R.view(incrementLens)
) 是 1f
(R.over(arrayLens, R.map(doIncrement))
)是一个等待值的函数(不是另一个函数)
在 g(x)
上应用 f
(R.over...
) 在非对象值上应用透镜,即使它是一个对象,结果也会是另一个值,这意味着你没有一个函数可以应用于管道中 setIncrementToOne
的结果。
在这种情况下 g(x)
的结果需要是一个函数,它可以被 R.over
与 arraylens
一起使用 - 以获得 R.over(arrayLens, R.map(R.add(1)))
,它等同于 incrementA
.
注意:我已将 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>