Как перевести многовариантный комбинатор с фиксированной точкой на строгий язык? - PullRequest
4 голосов
/ 05 апреля 2019

Я пытаюсь перевести следующий код на Haskell в Javascript:

fix_poly :: [[a] -> a] -> [a]
fix_poly fl = fix (\self -> map ($ self) fl)
  where fix f = f (fix f)

У меня проблемы с пониманием ($ self) хотя. Вот что я достиг на данный момент:

const structure = type => cons => {
  const f = (f, args) => ({
    ["run" + type]: f,
    [Symbol.toStringTag]: type,
    [Symbol("args")]: args
  });

  return cons(f);
};

const Defer = structure("Defer") (Defer => thunk => Defer(thunk));

const defFix = f => f(Defer(() => defFix(f)));

const defFixPoly = (...fs) =>
  defFix(self => fs.map(f => f(Defer(() => self))));

const pair = defFixPoly(
  f => n => n === 0
    ? true
    : f.runDefer() [1] (n - 1),
  f => n => n === 0
    ? false
    : f.runDefer() [0] (n - 1));

pair[0] (2); // true expected but error is thrown

Ошибка: Uncaught TypeError: f.runDefer(...)[1] is not a function.

Вот источник .

Ответы [ 2 ]

2 голосов
/ 05 апреля 2019

Определение defFixPoly имеет дополнительный слой Defer, чем следовало бы. Поскольку self уже является значением Defer, вы можете просто передать его непосредственно в f, а не переносить его снова.

const defFixPoly = (...fs) =>
  defFix(self => fs.map(f => f(self)));

const structure = type => cons => {
  const f = (f, args) => ({
    ["run" + type]: f,
    [Symbol.toStringTag]: type,
    [Symbol("args")]: args
  });

  return cons(f);
};

const Defer = structure("Defer") (Defer => thunk => Defer(thunk));

const defFix = f => f(Defer(() => defFix(f)));

const defFixPoly = (...fs) =>
  defFix(self => fs.map(f => f(self)));

const pair = defFixPoly(
  f => n => n === 0
    ? true
    : f.runDefer() [1] (n - 1),
  f => n => n === 0
    ? false
    : f.runDefer() [0] (n - 1));

console.log(pair[0] (2)); // true expected

Теперь это определяет взаимно рекурсивные функции isEven и isOdd.

const isEven = pair[0];
const isOdd = pair[1];
2 голосов
/ 05 апреля 2019

($ self) - это просто \f -> f $ self; это функция, которая применяет свой аргумент к self. Вы можете переписать версию на Haskell, используя понимание списка:

fix_poly fl = fix (\self -> [f self | f <- fl])
    where fix f = f (fix f)
...