在函数式编程中,默认情况下可以并行计算类似if (a || b)
的语句,因为由于引用透明性,我们不会对计算顺序做出任何假设.有什么简单的方法可以在C#中为条件语句引入这种类型的函数并行吗?
例如,在C#中,我们可以使用Parallel.For()
轻松地在for循环上引入并行性,所以我想知道是否有类似于条件的东西?
我正在try 将函数式编程的一些好处带到我编写C#的方式中.
在函数式编程中,默认情况下可以并行计算类似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
这里,b
是undefined
,这意味着实际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操作.
不是说有两个(或更多)昂贵的布尔表达式,而是引用透明的布尔表达式,这是完全不可想象的.如果你在密码学、蛋白质折叠等领域工作,我想你可能有两个布尔表达式,a
和b
,它们都是引用透明的,而且计算成本很高.
虽然这并不是不可想象的,但这似乎是一个足够小众的问题,我不指望主流语言会把这一点作为语言本身的一个功能.
由于a comment中有Dai个写入,因此并发会带来开销,因此表达式需要比开销高出more,才能保证这样的优化.
您能编写一个API将您带到那里吗?是的,当然可以,我相信在座的其他人也会告诉你如何使用Task.WhenAll和Task.WhenAny.
如果您需要关于如何设计这样的API的提示,考虑布尔比较形成monoids和all 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应该是什么样子.