Чем отличается Карри между Святилищем и Рамдой?

Я застрял с примерами карри в "Профессор Фрисби..." при использовании Sanctuary вместо Ramda. Я получаю сообщение об ошибке: "curry2 ожидал не более трех аргументов, но получил пять аргументов". пока с рамдой работает нормально. Я уверен, что я делаю что-то не так, но я не могу понять это.

Следуя примеру книги:

var match = curry2((what, str) => {return str.match(what);});
var hasSpaces = match(/\s+/g);
var filter = curry2((f, ary) => {return ary.filter(f);});
var f2 = filter(hasSpaces, ["tori_spelling", "tori amos"]);

я получил

TypeError: Function applied to too many arguments
curry2 :: ((a, b) -> c) -> a -> b -> c
‘curry2’ expected at most three arguments but received five arguments.

1 ответ

Решение

Святилище намного строже Рамды. Это гарантирует, что функции всегда применяются только к правильному количеству аргументов и что аргументы относятся к ожидаемым типам. S.add(42, true) например, ошибка типа, тогда как R.add(42, true) оценивает 43,

Проблема в вашем случае заключается в том, что Array#filter применяет данную функцию к трем аргументам (element, index, array). hasSpaces Впрочем, ожидает ровно один аргумент.

Решение заключается в использовании S.filter скорее, чем Array#filter:

const match = S.curry2((what, str) => str.match(what));
const hasSpaces = match(/\s+/g);
const f2 = S.filter(hasSpaces, ['tori_spelling', 'tori amos']);

Сделав это изменение, выявляется еще одна ошибка типа:

TypeError: Invalid value

filter :: (Applicative f, Foldable f, Monoid f) => (a -> Boolean) -> f a -> f a
                                                         ^^^^^^^
                                                            1

1)  null :: Null

The value at position 1 is not a member of ‘Boolean’.

See https://github.com/sanctuary-js/sanctuary-def/tree/v0.12.1#Boolean for information about the Boolean type.

S.filter ожидает предикат в качестве первого аргумента. В строгом смысле предикат - это функция, которая возвращает либо true или же false, String#match Тем не менее, возвращает либо null или массив совпадений.

Решение заключается в использовании S.test скорее, чем String#match:

const hasSpaces = S.test(/\s+/);
const f2 = S.filter(hasSpaces, ['tori_spelling', 'tori amos']);

На данный момент определение hasSpaces настолько ясно, что нет особой ценности дать ему имя. Мы можем написать код в виде одного выражения:

S.filter(S.test(/\s/), ['tori_spelling', 'tori amos'])

Обратите внимание, что шаблон может быть упрощен из /\s+/g в /\s/, g флаг не имеет никакого эффекта при использовании S.test и + не нужно, так как нас интересуют строки с пробелами, но мы не заинтересованы в подсчете пробелов.

Другие вопросы по тегам