Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining validations with scalaz 7

Given the following functions:

def foo( a: A ): ValidationNEL[String,Seq[B]] = ...

def bar( b: B ): ValidationNEL[String,C] = ...

I would like to combine them such as to build a function, which calls foo then eventually calls bar on each elements in the produced Seq, such a to get a ValidationNEL[String,Seq[C]]:

def fooAndBar( a: A ): ValidationNEL[String,Seq[C]]

Documentation in Scalaz 7 is very short and I could not find any relevant example.

like image 210
paradigmatic Avatar asked Aug 11 '12 11:08

paradigmatic


2 Answers

Do a hardcore traversal on the B sequence. Note that I used List here since Scalaz 7 doesn't seem to have typeclass instances for Seq, however it should not be too hard to write your own if really needed.

import scalaz.{ValidationNEL, Traverse, NonEmptyList}
import scalaz.std.list.listInstance
case class A(a: Int)
case class B(b: Int)
case class C(c: Int)

def foo( a: A ): ValidationNEL[String,List[B]] = Validation.success(List(B(1), B(2)))
def bar( b: B ): ValidationNEL[String,C] = Validation.failure(NonEmptyList("error in " + b.b))//Validation.success(C(b.b * 2))

type ValNEL[A] = ValidationNEL[String, A]

def foobar(a: A): ValidationNEL[String, List[C]] =
  foo(a) flatMap { bs =>
    Traverse[List].traverse[ValNEL, B, C](bs)(bar)
  }

val r: scalaz.ValidationNEL[String, List[C]] = foobar(A(3))

Update: Also see the invaluable Haskellwiki Typeclassopedia

like image 89
ron Avatar answered Nov 09 '22 09:11

ron


Have a look at this gist using kleisli to do this with Either https://gist.github.com/3240574 and this with Validation https://gist.github.com/3230464

like image 42
Channing Walton Avatar answered Nov 09 '22 09:11

Channing Walton