【问题标题】:Non-determinstic choice with amb-operatoramb-operator 的非确定性选择
【发布时间】:2010-11-07 23:43:58
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案1】:

    是的,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 =&gt; 1n =&gt; 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 完全不同。 Amb 选择它的值,这样整个代码就不会失败,而不仅仅是以下计算。
    • “重启”必须限制在特定的上下文中,但是它是如何实现的;具体来说,重新启动整个程序(包括在引入 amb 变量之前完成的所有工作)将是愚蠢的!在我的版本中,这是通过将 amb 变量引导到一个序列中来明确的,然后可重新启动的上下文是传递给 First 的 lambda - 请参阅上面的更新,这可能会更清楚。 lambda中的代码可以任意复杂。
    • 同意,不错的代码,但这是一个确定性的蛮力实现。这不是一个并发的非确定性实现,我认为这是实现 AMB 运营商的两个关键属性。附带说明一下,自从这篇文章以来,Rx 已经发布,并且确实有一个 Amb 运算符。
    【解决方案2】:

    这不是您问题的答案,但它可能会得到您想要的。

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

    在 C# 中有一个此功能的实现,称为 YieldProlog。正如您所猜测的那样,yield 运算符是一个重要的必要条件。

    http://yieldprolog.sourceforge.net/

    【讨论】:

      猜你喜欢
      • 2021-10-17
      • 2016-05-14
      • 2017-01-13
      • 2013-12-13
      • 1970-01-01
      • 2012-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多