我一直在尝试在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”(这是使用逻辑组合器的最简单的无限循环,尽管这将涉及稍后的一些蹦床以避免吹掉堆栈)。
答案 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缩减非常简单。