在C#

时间:2017-07-18 22:12:33

标签: c# lambda lambda-calculus

我一直在尝试在C#上实现原始的lambda演算,但我在实现它时遇到了一些麻烦,因为最后,我总是被要求提供对象。

我想要一些东西,例如,我可以定义一些基本的逻辑组合器,例如

I = Lambda x. x
M = Lambda x. x(x)

但是C#似乎运行的假设是它最终会获得一个对象。我试图以各种方式定义它们,例如

using lambda = Func<Object, Object>;
using lambda = Func<Func<Object, Object>, Func<Object, Object>>;
using lambda = Func<Func, Func>;

等等,但要么不遵守语法,要么与

不兼容
lambda I = x => x;
lambda M = x => x(x);

我尝试使用委托

public delegate object lambda(Object o);

static object i(object o)
{
    return o;
}

static object m(object o)
{
    return ((lambda)o)(o);
}

但最后,这些函数的任何实际使用仍然需要在行尾的参数,以及像

这样的伪参数
m(m(i('')));

只会导致执行期间的强制转换错误。

有没有办法在本地实现无类型lambda演算,还是我必须回到字符串处理?

对于执行程序的示例,它看起来像这样。对于以下功能:

lambda i(lambda x)
{
    print("i");
    return x;
}

lambda m(lambda x)
{
    print("m");
    return x(x);
}

(m(m))(i)的执行应该像m(m)一样被评估,在打印“m”之后返回m(m),这给了我们原来的(m(m))( i),然后将打印无限量的“m”(这是使用逻辑组合器的最简单的无限循环,尽管这将涉及稍后的一些蹦床以避免吹掉堆栈)。

1 个答案:

答案 0 :(得分:2)

您应该将其编码为抽象语法树,而不是将lambda表达式编码为Func<,>(这可能与 untyped lambda演算不是很好的匹配)。像这样:

public class LambdaAbstraction: ILambdaExpression {
    public LambdaVariable Variable { get; set; }
    public ILambdaExpression Body { get; set; }
}

public class LambdaApplication: ILambdaExpression {
    public ILambdaExpression Function { get; set; }
    public ILambdaExpression Argument { get; set; }
}

public class LambdaVariable: ILambdaExpression {
    public string Name { get; set; }
}

例如,M

ILambdaExpression M = new LambdaAbstraction {
   Variable = new LambdaVariable { Name = "x" },
   Body = new LambdaApplication {
       Function = new LambdaVariable { Name = "x" },
       Argument = new LambdaVariable { Name = "x" }
   }
}

然后,在此数据结构上实施递归方法进行alpha重命名和beta缩减非常简单。