如何将多变量定点组合器翻译成严格的语言?

时间:2019-04-05 12:18:03

标签: javascript haskell recursion functional-programming mutual-recursion

我正在尝试将以下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

这里是source

2 个答案:

答案 0 :(得分:2)

($ self)只是\f -> f $ self;它是一个将其参数应用于self的函数。您可以使用列表理解来重写Haskell版本:

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

答案 1 :(得分:2)

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

现在,它定义了相互递归的isEvenisOdd函数。

const isEven = pair[0];
const isOdd = pair[1];