amb-operator的非确定性选择

时间:2009-07-03 17:12:00

标签: c# .net functional-programming continuations non-deterministic

是否可以在C#中实现McCarthy's amb-operator非确定性选择?

显然.NET缺乏持续支持,但yield return可能有用。这是否可以用于其他静态.NET语言,如F#?

2 个答案:

答案 0 :(得分:5)

是的,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 => 1n => 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而没有参数。

答案 1 :(得分:5)

这不是你问题的答案,但可能会得到你想要的东西。

amb用于非确定性计算。您可能知道,Prolog是一种非确定性语言,它使用统一的概念将值绑定到变量(基本上是amb最终要做的事情)。

在C#中有一个名为YieldProlog的实现。正如您所猜测的那样,收益率算子是一个重要的必要条件。

http://yieldprolog.sourceforge.net/