Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nice syntax for Validation in another monad

I like monad transformers. For example, I can combine nicely two future optional values like this:

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

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

Since Validation doesn't have a Monad[_] instance, I can't use similar syntax for it. What is the best way, how to sum these two:

val val3:Task[ValidationNel[Throwable,Int]] = ???
val val4:Task[ValidationNel[Throwable,Int]] = ???
like image 514
ryskajakub Avatar asked Apr 26 '26 03:04

ryskajakub


2 Answers

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!))
like image 130
pawel.panasewicz Avatar answered Apr 28 '26 22:04

pawel.panasewicz


If you define a semigroup instance for Int, you can just add the validations together to get back one Task[ValidationNel[Throwable,Int]]:

  val sum2 = for {
    three ← val3
    four ← val4
  } yield three +|+ four
like image 34
Noah Avatar answered Apr 28 '26 21:04

Noah



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!