В моем предыдущем вопросе:
Извлечение данных из цепочки функций без массивов
@Aadit M Shah дал мне удивительное решение следующим образом:
https://stackoverflow.com/a/51420884/6440264
По такому выражению, как A(a)(b)(f)
, где f
– это функция, невозможно определить, следует ли добавить f
в список или это функция сокращения. Поэтому я собираюсь описать, как писать такие выражения, как A(a)(b)(f, x)
, что эквивалентно [a, b].reduce(f, x)
. Это позволяет нам различать, когда заканчивается список, в зависимости от того, сколько аргументов вы предоставляете:
const L = g => function (x, a) {
switch (arguments.length) {
case 1: return L(k => g((f, a) => k(f, f(a, x))));
case 2: return g((f, a) => a)(x, a);
}
};
const A = L(x => x);
const xs = A(1)(2)(3)(4)(5);
console.log(xs((x, y) => x + y, 0)); // 15
console.log(xs((x, y) => x * y, 1)); // 120
console.log(xs((a, x) => a.concat(x), [])); // [1,2,3,4,5]
Это работает благодаря продолжениям. Каждый раз, когда мы добавляем новый элемент, мы накапливаем функцию CPS. Каждая функция CPS вызывает предыдущую функцию CPS, тем самым создавая цепочку функций CPS. Когда мы даем этой цепочке функций CPS базовую функцию, она разворачивает цепочку и позволяет нам сократить ее. Та же идея лежит в основе преобразователей и линзы.
У меня осталось 2 вопроса.
Чтобы различать функцию сокращения, я рассматриваю некий пользовательский механизм Typing с использованием отражения, но чтобы сосредоточиться на этом вопросе, пока я хотел бы просто применить
const isReducer = f => (typeof f === 'функция');
Требование предоставить начальное значение имеет ограничение на свертывание/уменьшение, например, невозможно предоставить начальное значение для бинарных операций для сокращения, таких как
const head = (a, b) => a; const хвост = (а, б) => б;
(если вы не укажете первое/последнее значение вручную, что не имеет смысла запускать код) Теоретически каждая двоичная операция имеет значение идентичности, но что-то невозможно предоставить как есть. Единственный способ — абстрагироваться как личность.
Сказав это, я не могу реорганизовать предоставленный код в одиночные аргументы и по типу редуктора функции, а значение по умолчанию - в качестве начального значения последовательности.
Можете ли вы предоставить код рефакторинга? Также приветствуется любая информация о датчике/CPS для этого примера.
head
иtail
— они в любом случае не являются допустимыми бинарными операциями дляreduce
, так как их типы не подходят. Пожалуйста, перестаньте злоупотреблять типами функций как структурами данных, и вы поймете, почему. - person Bergi   schedule 19.07.2018(a,b)=> a
или(a,b)=> b
ЯВЛЯЕТСЯ бинарной операцией. Если вы не настаиваете, пожалуйста, дайте нам ссылку. - person   schedule 19.07.2018reduce
, но голова и хвост ассоциативны, поэтому они являются допустимыми операторами дляreuduce
- person   schedule 19.07.2018head
иtail
. Обычно вы связываете их со списками, где они имеют типыlist<a> -> a
иlist<a> -> list<a>
, которые вообще не являются бинарными операциями. - person Bergi   schedule 19.07.2018head = (a,b)=> a
иtail = (a,b)=> b
. По сути это известные бинарные операторы редуктора моноидов. Я дам вам образец в моем ответе здесь. - person   schedule 20.07.2018head
иlast
. Когда вы сказалиtail
, это смутило и Берги, и меня, потому что конец списка — это все, кроме первого элемента. - person Aadit M Shah   schedule 20.07.2018last
. - person   schedule 20.07.2018