C# amb算子的非确定性选择

C# amb算子的非确定性选择,c#,.net,functional-programming,continuations,non-deterministic,C#,.net,Functional Programming,Continuations,Non Deterministic,是否可以在C#中实现非确定性选择 显然.NET缺乏延续性支持,但是收益率可能会很有用。在其他静态.NET语言中,如F#?是的,yield-return是一种延续形式。尽管在许多有用的情况下,Linq提供了函数运算符,允许您插入一个惰性序列生成器,因此实际上在C#3中,不需要使用太多的yield return(除非添加更多自己的Linq样式扩展来插入库中的间隙,例如Zip、Unfold) 在这个例子中,我们用蛮力分解一个整数。本质上,C#中的相同示例可以通过内置Linq操作符完成: var fac

是否可以在C#中实现非确定性选择


显然.NET缺乏延续性支持,但是
收益率
可能会很有用。在其他静态.NET语言中,如F#?

是的,
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;
}
最后,我选择了第一个满足测试要求的元组:

.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。正如您所猜测的,收益率操作符是实现这一点的重要必要条件


代码不错-但它的效果与amb截然不同。Amb选择它的值,这样整个代码就不会失败,而不仅仅是下面的计算;具体来说,重新启动整个程序(包括引入amb变量之前所做的所有工作)是愚蠢的!在我的版本中,这是通过将amb变量导入一个序列来明确的,然后可重启上下文是传递给First的lambda-请参阅上面的更新,这可能会更清楚。lambda中的代码可能任意复杂。同意,代码不错,但这是一个确定性的暴力实现。这不是一个并发的非确定性实现,我认为这是实现AMB操作符的两个关键属性。作为旁注,由于这篇文章,Rx被发布了,并且确实有一个Amb操作员。
.First(v => 
       {
           Console.WriteLine("Aren't lambdas powerful things?");

           return v.i*v.j == 481;
       );