Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert an Option[Validation[E, A]] to a Validation[E, Option[A]]

In ScalaZ, what is the idiomatic way to convert an Option[Validation[E, A]] to a Validation[E, Option[A]]?

For example, in the following hypothetical code:

def convert(x: Option[Validation[E, A]]): Validation[E, Option[A]] =    
  /* ??? */

def validateThing(thing: A): Validation[E, A] = 
  /* whatever */

def exampleUseCase(maybeThing: Option[Thing]): Validation[E, Option[Thing]] = {
  val validated: Option[Validation[E, Thing]] = a.map(validateThing(_))

   // ...

  val result: Validation[E, Option[Thing]] = convert(validated)
  result 
}

what would the implementation of convert look like in idiomatic ScalaZ?

like image 880
kes Avatar asked Sep 26 '22 08:09

kes


1 Answers

I can see two possible solutions here. Probably the easiest one using pattern matching on the argument, example:

def convert[A](v: Option[Validation[Throwable, A]]): Validation[Throwable, Option[A]] = {
  v match {
    case None => Validation.success(None)
    case Some(valid) => valid.map(Some(_))
  }
}

For Scalaz based solution, i was thinking about sequence, this way you need to use ValidationNel instead of Validation, to aggregate possible issues, the you can implement convert with Traversable:

def convert[A](v: Option[ValidationNel[Throwable, A]]): ValidationNel[Throwable, Option[A]] = 
  Traverse[Option].sequenceU(v)

Please note that in fact i'm using sequenceU instead of just sequence, it's nothing more than internal Scalaz magic for proper type inference, cause Validation has two type parameters. Hope it helps

like image 185
4lex1v Avatar answered Oct 20 '22 13:10

4lex1v