scala中应用计算和单子计算之间的区别

Difference between applicative and monadic computation in scala

考虑到这个简单的计算,我无法清楚地看到使用应用风格与单子风格之间的区别。是否有一些更好的例子(在 scala 中)何时使用一个而不是另一个。

    println( (3.some |@| none[Int] |@| 4.some )( (a:Int,b:Int,c:Int) => {  a + b + c } )  ) // prints None

    println( for( 
     a <- Some(3);
     b <- none[Int];
     c <- Some(4)
   ) yield( a + b + c ) ) // prints None

两次计算都以 None 结束,所以最终结果是相同的。我能看到的唯一区别是,在使用应用语法时,无法临时访问 for comprehension 中的那些变量。

此外,有一个 None 值会停止整个计算。我认为应用意味着 "not dependent on the result of the computation before"

applicative builder 语法将评估每个术语,不能使用先前计算的结果。但是,即使第一个结果是 None,所有其他表达式仍将被计算。

然而,对于 for 理解,它将 'fail fast'(在您的情况下,它不会在 None 之后评估任何进一步的表达式),而且您可以访问先前计算的结果。

不要认为这些东西只是简单的不同 styles,它们调用具有不同行为的不同函数:即 flatMap 与 apply

Monads 表示 顺序 计算,其中每个下一个计算都取决于前一个计算(如果前一个计算为空,则无法继续,因此 "fail fast"),更通用一元计算的例子:

println( for( 
     a <- Some(1);
     b <- Some(a);
     c <- Some(a + b)
   ) yield( a + b + c ) ) //=> 4

Applicative 只是 fmap 类固醇,其中不仅参数而且映射函数本身都可以为空。在您的情况下,它可以重写为:

4.some <*>
  { none[Int] <*>
    { 3.some <*> 
      { (_: Int) + (_: Int) + (_: Int) }.curried.some } }

在某些步骤中,您的函数变为 Option[Int => Int] = None,但它不会停止将其应用于 4.some,只是结果如预期的那样 None。您仍然需要知道 4.some.

的值