3

我喜欢单子变压器。例如,我可以很好地组合两个未来的可选值,如下所示:

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]] = ???
4

2 回答 2

2

You are probably looking for way to accumulate errors or compute result. You may be interested in macculkin operator, I mean a pipe at pipe or |@| (choose the name you like most) ;)

Example of usage. See how errors are accumulated (OMG! and Holly mum! are included in result.

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!))

The often made mistake is when you choose to use for comprehension or map functions. When you decide follow such way you will not able to acumulate errors. Only OMG! is accumulated. See below:

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

//res0: scalaz.Validation[scalaz.NonEmptyList[Throwable],Int] = Failure(NonEmptyList(java.lang.RuntimeException: OMG!))
于 2013-10-18T14:41:24.720 回答
1

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

  val sum2 = for {
    three ← val3
    four ← val4
  } yield three +|+ four
于 2013-10-18T15:36:48.487 回答