我有兩個monad實例val a: M[A]
和val b: M[B]
。在下面的代碼情況下會有任何性能差異嗎?應用函數vs monad在Scala中構成性能
def f: (A, B) => C
val applicativeCombine = (a |@| b)(f)
val monadCombine =
for {
aa <- a
bb <- b
} yield f(aa, bb)
...還是它取決於?
我有兩個monad實例val a: M[A]
和val b: M[B]
。在下面的代碼情況下會有任何性能差異嗎?應用函數vs monad在Scala中構成性能
def f: (A, B) => C
val applicativeCombine = (a |@| b)(f)
val monadCombine =
for {
aa <- a
bb <- b
} yield f(aa, bb)
...還是它取決於?
如果a
和b
是返回期貨和執行一些計算昂貴的操作方法,該applicativeCombine
版本將並行運行它們而monadCombine
不會,這意味着|@|
可能接近兩倍的速度。
如果a
和b
是期權,另一方面,甚至期貨沒有被做計算量很大的工作,它有可能是for
版本可能會更快,因爲它的脫糖形式涉及一對夫婦少分配:
scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> showCode(reify((Option(1) |@| Option(2))(_ + _)).tree)
res0: String = Scalaz.ToApplyOps(Option.apply(1))(Scalaz.optionInstance).|@|(Option.apply(2)).apply(((x$1, x$2) => x$1.+(x$2)))(Scalaz.optionInstance)
scala> showCode(reify(for { a <- Option(1); b <- Option(2) } yield a + b).tree)
res1: String = Option.apply(1).flatMap(((a) => Option.apply(2).map(((b) => a.+(b)))))
(但是,這是不太可能在大多數程序中有意義的差異。)
如果這是貓和a
和b
是eithers和你有「錯誤」的進口,從而使你得到FlatMapSyntax
和EitherInstances
而不是EitherSyntax
,|@|
版本可能會再次更快,因爲for
版本將導致至少一些額外的Unapply
實例和一些其他的東西。
所以簡短的答案是肯定的,這取決於,如果你真的關心性能,你需要爲你的特定用例做仔細的基準測試。
儘管更喜歡應用版本的最佳理由與性能沒有任何關係,但它是您要執行的計算的更精確表示。你的a
和b
不相互依賴,但for
-compprehension表示他們這樣做。有關更多討論,請參閱我的回答here。
您應該添加一個'scalaz'標記,因爲從問題本身不清楚'| @ |'是從哪裏來的。 –