在函数式编程中,默认情况下可以并行计算类似if (a || b)的语句,因为由于引用透明性,我们不会对计算顺序做出任何假设.有什么简单的方法可以在C#中为条件语句引入这种类型的函数并行吗?

例如,在C#中,我们可以使用Parallel.For()轻松地在for循环上引入并行性,所以我想知道是否有类似于条件的东西?

我正在try 将函数式编程的一些好处带到我编写C#的方式中.

推荐答案

虽然在理论上是可能的,但我还没有听说过有任何语言通过语法或简单的API来支持这一点(但我也只知道少数几种语言).正如您可能知道的,Haskell通常被认为是FP的黄金标准,但Haskell中的布尔表达式只是普通的、短路的表达式,就像它们在C#中一样.

ghci> a = True
ghci> b = undefined
ghci> (a || b)
True

这里,bundefined,这意味着实际try 计算它将引发异常:

ghci> b
*** Exception: Prelude.undefined
CallStack (from HasCallStack):
  error, called at libraries\base\GHC\Err.hs:74:14 in base:GHC.Err
  undefined, called at <interactive>:2:5 in interactive:Ghci2

但正如您在上面的示例中看到的,(a || b)的计算结果为True,因为它会短路.

事实上,Haskell通常会因为懒惰的求值而自动短路,但大多数语言都有短路布尔表达式.

这已经是一个很好的优化了.如果你有一个便宜的布尔表达式和一个昂贵的布尔表达式,把便宜的放在第一位.

那么,您多久会需要比这更多的优化呢?尤其是在参照透明函数的情况下.通常,昂贵的操作涉及I/O操作.

不是说有两个(或更多)昂贵的布尔表达式,而是引用透明的布尔表达式,这是完全不可想象的.如果你在密码学、蛋白质折叠等领域工作,我想你可能有两个布尔表达式,ab,它们都是引用透明的,而且计算成本很高.

虽然这并不是不可想象的,但这似乎是一个足够小众的问题,我不指望主流语言会把这一点作为语言本身的一个功能.

由于a comment中有Dai个写入,因此并发会带来开销,因此表达式需要比开销高出more,才能保证这样的优化.

您能编写一个API将您带到那里吗?是的,当然可以,我相信在座的其他人也会告诉你如何使用Task.WhenAllTask.WhenAny.

如果您需要关于如何设计这样的API的提示,考虑布尔比较形成monoidsall monoids can be made lazy可能会有所帮助:

Lazy<bool> x = // ...
Lazy<bool> y = // ...
Lazy<bool> b = x.And(y);

您可以使用第三方物流做类似的事情,因为您可以:

(Applicative f, Monoid a) => Monoid (Ap f a)

C# Tasks are monads开始,它们也是applicative functors,所以我们从Haskell那里知道这是可能的,以及API应该是什么样子.

Csharp相关问答推荐

从C#网站调用时找不到存储过程

在Microsoft XNA框架(MonoGame)中旋转相机

react 式扩展连接中的非交叉LeftDurationTimeout

向类注入一个工厂来创建一些资源是一个好的实践吗?

C#自定义字典与JSON(de—)serialize

. NET 8使用COM向VB6公开

使用LINQ to XML获取元素值列表是不起作用的

不仅仅是一个简单的自定义按钮

如何通过属性初始化器强制初始化继承记录内的属性?

确定System.Text.Json序列化中是否无法识别Type

正确处理嵌套的本机集合

是否有必要在ASP.NET Core中注册可传递依赖项?

在.NET 8最低API中从表单绑定中排除属性

如何将FindAll()与Nuget包Interop.UIAutomationClient一起使用

为什么我不能从我的异步任务方法中返回异步任务方法?

发布.NET 8 Blazor WebAssembly独立应用程序以进行静态站点部署

Xamarin Forms应用程序中登录页面的用户名和密码编辑文本之间不需要的空格

SignalR跨域

读取测试项目中的应用程序设置

为什么我不能在固定语句中使用外部函数?