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

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

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?

1 Ответ

0 голосов
/ 12 декабря 2018

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

  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]
...