【发布时间】:2010-11-07 23:43:58
【问题描述】:
是否可以在 C# 中为非确定性选择实现 McCarthy's amb-operator?
显然 .NET 缺乏持续支持,但 yield return 可能有用。这在 F# 等其他静态 .NET 语言中是否可行?
【问题讨论】:
标签: c# .net functional-programming continuations non-deterministic
是否可以在 C# 中为非确定性选择实现 McCarthy's amb-operator?
显然 .NET 缺乏持续支持,但 yield return 可能有用。这在 F# 等其他静态 .NET 语言中是否可行?
【问题讨论】:
标签: c# .net functional-programming continuations non-deterministic
是的,yield return 是一种延续形式。尽管对于许多有用的情况,Linq 提供了函数式运算符,允许您将惰性序列生成器插入到一起,因此实际上在 C# 3 中没有必要过多地使用 yield return(除非添加更多的 Linq 样式的扩展自己来填补库中的空白,例如 Zip、Unfold)。
在示例中,我们通过蛮力对整数进行因式分解。本质上,C# 中的相同示例可以使用内置的 Linq 运算符完成:
var factors = Enumerable.Range(2, 100)
.Join(Enumerable.Range(2, 100),
n => 1, n => 1, (i, j) => new { i, j })
.First(v => v.i*v.j == 481);
Console.WriteLine("Factors are " + factors.i + ", " + factors.j);
这里的起点是我对Enumerable.Range 的两次调用,这是 Linq 内置的,但您可以将自己实现为:
IEnumerable<int> Range(int start, int stop)
{
for (int n = start; n < stop; n++)
yield return n;
}
有两个奇数参数,n => 1、n => 1 参数到Join。我选择 1 作为 Join 在匹配项目时使用的键值,因此所有组合都将匹配,因此我可以测试范围内的每个数字组合。
然后我将这对值转换为一种元组(匿名类型):
(i, j) => new { i, j })
最后,我选择第一个满足我的测试的元组:
.First(v => v.i*v.j == 481);
更新
First 调用中的代码不必仅仅是一个简短的测试表达式。如果测试失败,可能需要“重新启动”大量命令式代码:
.First(v =>
{
Console.WriteLine("Aren't lambdas powerful things?");
return v.i*v.j == 481;
);
因此,可能需要使用不同值重新启动的程序部分进入该 lambda。每当该 lambda 想要使用不同的值重新启动自身时,它只会返回 false - 相当于在不带参数的情况下调用 amb。
【讨论】:
这不是您问题的答案,但它可能会得到您想要的。
amb 用于非确定性计算。您可能知道,Prolog 是一种非确定性语言,它使用统一的概念将值绑定到变量(基本上是 amb 最终会做的事情)。
在 C# 中有一个此功能的实现,称为 YieldProlog。正如您所猜测的那样,yield 运算符是一个重要的必要条件。
【讨论】: