Как реализовать сопрограмму для аппликативных вычислений? - PullRequest
0 голосов
/ 02 февраля 2019

Вот сопрограмма, которая избегает вложенных шаблонов, таких как (chain(m) (chain(...)) для монадических вычислений:

const some = x => none => some => some(x);
const none = none => some => none;

const option = none => some => tx => tx(none) (some);
const id = x => x;

const of = some;
const chain = fm => m => none => some => m(none) (x => fm(x) (none) (some));

const doM = (chain, of) => gf => {
  const it = gf();

  const loop = ({done, value}) =>
    done
      ? of(value)
      : chain(x => loop(it.next(x))) (value);

  return loop(it.next());
};

const tx = some(4),
  ty = some(5),
  tz = none;

const data = doM(chain, of) (function*() {
  const x = yield tx,
    y = yield ty,
    z = yield tz;

  return x + y + z;
});

console.log(
  option(0) (id) (data)); // 0

Но я не могу реализовать эквивалентную сопрограмму для аппликативных вычислений:

const some = x => none => some => some(x);
const none = none => some => none;

const option = none => some => tx => tx(none) (some);
const id = x => x;

const of = some;
const map = f => t => none => some => t(none) (x => some(f(x)));
const ap = tf => t => none => some => tf(none) (f => t(none) (x => some(f(x))));

const doA = (ap, of) => gf => {
  const it = gf();

  const loop = ({done, value}, initial) =>
    done
      ? value
      : ap(of(x => loop(it.next(x)))) (value);

  return loop(it.next());
};

const tx = some(4),
  ty = some(5),
  tz = none;

const data = doA(ap, of) (function*() {
  const x = yield tx,
    y = yield ty,
    z = yield tz;

  return x + y + z;
});

console.log(
  option(0) (id) (data)); // none => some => ...

Это должно работать, но это не так.Откуда берется дополнительная функториальная упаковка?Я думаю, что я немного потерян в рекурсии здесь.

Кстати, я знаю, что это работает только для детерминированных функторов / монад.

1 Ответ

0 голосов
/ 02 февраля 2019

Я не могу реализовать эквивалентную сопрограмму для аппликативных вычислений

Да, потому что функции генератора монадические, а не только аппликативные.Операнд выражения yield может зависеть от результата предыдущего выражения yield - это характерно для монады.

Откуда берется дополнительная функториальная упаковка?Полагаю, я немного растерялся.

Вы делаете ap(of(…))(…) - это эквивалентно map(…)(…) согласно Применимому законодательству .По сравнению с вызовом chain в первом фрагменте, это не приводит к развертыванию результата, поэтому вы получаете вложенный тип maybe (который в вашей реализации закодирован как функция).

...