在另一个monad中验证的语法很好

时间:2013-10-18 14:08:37

标签: scala scalaz monad-transformers

我喜欢monad变形金刚。 例如,我可以很好地结合两个未来的可选值,如下所示:

val val1:OptionT[Task, Int] = ???
val val2:OptionT[Task, Int] = ???

val sum = for {
  one ← val1
  two ← val2
} yield (one + two)

由于Validation没有Monad[_]实例,因此我无法使用类似的语法。什么是最好的方法,如何总结这两个:

val val3:Task[ValidationNel[Throwable,Int]] = ???
val val4:Task[ValidationNel[Throwable,Int]] = ???

2 个答案:

答案 0 :(得分:2)

您可能正在寻找累积错误或计算结果的方法。您可能对 macculkin operator 感兴趣,我的意思是管道管道或|@|(选择您最喜欢的名称);)

使用示例。了解如何累积错误( OMG! Holly妈妈!包含在结果中。

import scalaz._
import Scalaz._

val v1: ValidationNel[Throwable, Int] = 1.successNel
val v2: ValidationNel[Throwable, Int] = new RuntimeException("OMG!").failNel
val v3: ValidationNel[Throwable, Int] = new RuntimeException("Holly mom!").failNel

val sum : ValidationNel[Throwable, Int] = (v1 |@| v2 |@| v3 ) (_ + _ + _)
//scala> sum: scalaz.ValidationNel[Throwable,Int] = Failure(NonEmptyList(java.lang.RuntimeException: OMG!, java.lang.RuntimeException: Holly mom!))

经常犯的错误是当你选择用于理解或地图功能时。当您决定遵循这样的方式时,您将无法累积错误。只累积 OMG!。见下文:

for( val1 <- v1;
     val2 <- v2;
     val3 <- v3
    ) yield(val1 + val2 + val3)

//res0: scalaz.Validation[scalaz.NonEmptyList[Throwable],Int] = Failure(NonEmptyList(java.lang.RuntimeException: OMG!))

答案 1 :(得分:1)

如果为Int定义半群实例,则只需将验证一起添加即可返回Task[ValidationNel[Throwable,Int]]

  val sum2 = for {
    three ← val3
    four ← val4
  } yield three +|+ four