Почему мой преобразователь больше не работает при абстрагировании от редукции/композиции?

Я застрял в реализации короткого замыкания и безопасного стека преобразователя:

const loop = f => {
   let acc = f();

   while (acc && acc.type === tailRec)
     acc = f(...acc.args);

   return acc;
};

const tailRec = (...args) =>
   ({type: tailRec, args});

const arrFoldk = f => acc_ => xs =>
  loop((acc = acc_, i = 0) =>
    i === xs.length
      ? acc
      : f(acc) (xs[i]) (acc_ => tailRec(acc_, i + 1)));

const liftk2 = f => x => y => k =>
  k(f(x) (y));

const isOdd = n => n & 1 === 1;
const concat = xs => ys => xs.concat(ys);
const comp = f => g => x => f(g(x));
const id = x => x;

const filterReduce = filter => reduce => acc => x => k =>
  filter(x)
    ? reduce(acc) (x) (k)
    : k(acc);

const takeReduce = n => reduce => acc => x => k =>
  acc.length === n
    ? reduce(acc) (x) (id)
    : reduce(acc) (x) (k);

const fx = filterReduce(isOdd),
  fy = takeReduce(3),
  fz = comp(fy) (fx);

const transducek = (...fs) => xs =>
  arrFoldk(fs.reduce((f, g) => comp(f) (g), id) (liftk2(concat))) ([]);

const r1 = arrFoldk(fz(liftk2(concat))) ([]) ([1,2,3,4,5,6,7,8,9]);
const r2 = transducek(fx, fy) ([1,2,3,4,5,6,7,8,9]);

console.log(r1); // [1,3,5]
console.log(r2); // xs => ...

Я смотрю на код, и он совершенно ясно говорит мне, что вычисления, дающие r1 и r2 соответственно, по существу одинаковы. Почему я не получаю тот же результат при применении вспомогательной функции transduce?


person Community    schedule 11.12.2018    source источник


Ответы (1)


Не уверен, что это те ошибки, которые вы ищете, но меня поразили эти две вещи:

  1. Вы включили xs в сигнатуру transduceK, но никогда не вызывали составленную функцию с этим параметром. Либо добавьте (xs) в конец, либо просто выполните:

    const transducek = (...fs) =>
      arrFoldk(fs.reduce((f, g) => comp(f) (g), id) (liftk2(concat))) ([]);
    
  2. Эквивалентом comp (fy) (fx) является [fx, fy].reduceRight((g, h) => comp (g) (h), id) или [fx, fy].reduce((f, g) => comp(g) (f), id)

С этими изменениями, я думаю, все работает так, как задумано:

const loop = f => {
   let acc = f();

   while (acc && acc.type === tailRec)
     acc = f(...acc.args);

   return acc;
};

const tailRec = (...args) =>
   ({type: tailRec, args});

const arrFoldk = f => acc_ => xs =>
  loop((acc = acc_, i = 0) =>
    i === xs.length
      ? acc
      : f(acc) (xs[i]) (acc_ => tailRec(acc_, i + 1)));

const liftk2 = f => x => y => k =>
  k(f(x) (y));

const isOdd = n => n & 1 === 1;
const concat = xs => ys => xs.concat(ys);
const comp = f => g => x => f(g(x));
const id = x => x;

const filterReduce = filter => reduce => acc => x => k =>
  filter(x)
    ? reduce(acc) (x) (k)
    : k(acc);

const takeReduce = n => reduce => acc => x => k =>
  acc.length === n
    ? reduce(acc) (x) (id)
    : reduce(acc) (x) (k);

const fx = filterReduce(isOdd),
  fy = takeReduce(3),
  fz = comp(fy) (fx);

const transducek = (...fs) =>
  arrFoldk(fs.reduce((f, g) => comp(g) (f), id) (liftk2(concat))) ([]);

const r1 = arrFoldk(fz(liftk2(concat))) ([]) ([1,2,3,4,5,6,7,8,9]);
const r2 = transducek(fx, fy) ([1,2,3,4,5,6,7,8,9]);

console.log(r1); // [1,3,5]
console.log(r2); // [1,3,5]

person user3297291    schedule 11.12.2018
comment
Кодовая слепота — опять меня достало. Спасибо. - person ; 12.12.2018