2016-05-21 11 views
2

Я пытаюсь преобразовать следующий стиль в свободный от точки: функция, которая частично применяет значение к функции трансформатора add перед тем, как передать ее в итерацию. (Использование Ramda.js)Как я могу указать порядок применения параметра curries

R.compose(
    R.map, 
    R.add 
)(1, [1,2,3]) 

Проблема заключается в том, что R.add является арностью 2, как это R.map. Я хочу, чтобы порядок приложения будет следующим:

add(1) 
map(add(1)) 
map(add(1), [1,2,3]) 
[add(1,1), add(1,2), add(1,3)] 

Но что происходит, вместо того, чтобы это:

add(1, [1,2,3]) 
map(add(1, [1,2,3])) 
<partially applied map, waiting for collection> 

Каждый знает способ указать это поведение?

ответ

2

Простой compose или pipe не будет делать этого, потому что либо поглотит все аргументы, входящие в первую функцию. Ramda включает в себя две дополнительные функции, которые помогают с этим, converge и useWith. В этом случае useWith является тот, который поможет:

useWith(map, [add, identity])(1, [1, 2, 3]); //=> [2, 3, 4] 

Хотя identity не является абсолютно необходимым здесь, это дает сгенерированной функции правильной Арность.

+0

Это настолько элегантно. Спасибо (и я большой поклонник твоей работы)! – mLuby

+0

Возможно, он более изящный, но я никогда раньше не думал о вашей технике 'nAry' /' uncurry'. Это может быть более сложным для этого конкретного случая, но оно также более гибкое и более общее. Интересный материал. –

2

Выяснил это. Если кому-то интересно, вот суть. (Вы можете попробовать его в консоли на RamdaJS.com.)

0) Для базовой линии, здесь указана версия.

func0 = x => R.map(R.add(x)) 
addOne = func0(1) 
addOne([1,2,3]) // [2,3,4] 

1) Здесь ядро ​​pointfree, но проблема с этим вопросом связана с вопросом выше.

func1 = R.compose(R.map, R.add) 
addOne = func1(1) 
addOne([1,2,3]) // [2,3,4]) 
func1(1, [1,2,3]) // function 

2) Если композиция является unary (арностью 1) 2 вызовы нужно применять все Params.

func2 = R.unary(R.compose(R.map, R.add)) 
addOne = func2(1) 
addOne([1,2,3]) // [2,3,4]) 

3) Мы хотим, чтобы один вызов, чтобы применить оба Params, поэтому мы uncurry 2.

func3 = R.uncurryN(2, func2) 
func3(1, [1,2,3]) // [2,3,4]) 

4) Для того, чтобы доказать, func2 является компонуемы, давайте удвоить результаты.

func4 = R.compose(
    R.map(R.multiply(2)), 
    R.uncurryN(2, func2) 
) 
func4(1, [1,2,3]) // [4,6,8]) 

5) Замещение дает нам полностью свободную точку.

func5 = R.compose(
    R.map(R.multiply(2)), 
    R.uncurryN(2, R.unary(R.compose(
    R.map, 
    R.add 
))) 
) 
func5(1, [1,2,3]) // [4,6,8])