这是一个固定点组合器的实现吗?

时间:2013-07-23 21:02:08

标签: javascript functional-programming monads combinators

我认为这不能称为“定点递归”,因为它过于简单。但是,我最近意识到它实际上可能是。

我是否有效地实现了定点递归?

这是有问题的功能:

/* recursive kleisli fold */
var until = function(f) {
    return function(a) {
        return kleisli(f, until(f))(a);
    };
};

这是一些额外的背景:

// The error monad's bind
var bind_ = function(f, m) { return m.m === Success ? f(m.a) : m; };

var bind = function(f, m) {
    return m !== undefined && m.m !== undefined && m.a !== undefined ? bind_(f, m) : m;
};

var kleisli = function(f1, f2) { 
    return function(a) { 
        return bind(f2, f1(a)); 
    };
};

代码的其余部分为here,但上面的代码段应足以跟随。

1 个答案:

答案 0 :(得分:6)

定点组合子的定义是函数F,它接受​​函数f并返回函数p,以便

给定F(f) = p然后p = f(p)

可以编写许多可能的定点组合器。不要让直截了当让你认为某些东西不是定点组合者;这是JavaScript中的标准定义,非常简单:

  var fix = function(f) {
       return function(x) { 
        return f(fix(f))(x)
      }
  };

然后用一个用法来计算阶乘的定点,用:

var fact = function(f) { 
              return function(n) { return (n == 0) ? 1 : (n * f(n - 1)) } 
           };

alert(fix(fact)(7)); // alerts us with 5040.

有关不同定点组合子(Y组合子)的示例,请参阅this helpful blog post

让我们看看你的until组合子是否计算了固定点。由于您正在使用monadic函数,定点定义会稍微改变以处理monadic结构,其中F是一个(monadic)定点组合器

给定F(f) = p然后p = f* . p

其中f* . p表示函数p的Kleisli组合,其函数为f(在您的代码中,您将编写此kleisli(p, f),您可以想到{{1}作为*)。我将使用这种表示法,因为它比编写JavaScript更短。

让我们展开bind的定义然后看看我们得到了什么:

until

until(f) = (until(f))* . f = (until(f)* . f)* . f = ((... . f)* . f)* . f = ... . f* . f* . f (associativity of bind for a monad: (g* . f)* = g* . f*) = p 吗?

p = f* . p

是的 - 我相信。虽然我不认为这是一个有用的定点。 (我担心我还没有一个好的论据 - 但我认为这基本上是一个最大的固定点,只会出现分歧)。

对我而言,... . f* . f* . f =?= f* . ... . f* . f* . f kleisli的参数应该已被交换。也就是说,我们希望在until示例中使用Kleisli等效的应用程序,因此我们需要将递归调用fix的monadic结果传递给until(f)

f

让我们展开 var until = function(f) { return function(a) { return kleisli(until(f), f)(a); }; }; 的新定义:

until

until(f) = f* . until(f) = f* . (f* . until(f)) = f* . f* . ... = p 吗?是的确如此:

p = f* . p

因为在f *组合的无限链上再添加一个f *组成是相同的功能。

使用你的f* . f* ... = f* . (f* . f* . ...) 函数我遇到了一些分歧问题(某些评估过早发生,因此计算一直运行直到我的堆栈空间不足)。相反,以下似乎对我有用:

kleisli

有关monadic代码定点的更多信息,您可以查看the work of Erkök and Launchbury