I\'m trying to use Scalaz 7 Validation in my app. However, I\'m having an issue getting the |@|
applicative functor to coalesce my failures. Here\'s the code I
Scalaz's applicative builder syntax (|@|
) gives you a way of "lifting" functions into an applicative functor. Suppose we have the following results, for example:
val xs: ValidationNel[String, List[Int]] = "Error!".failNel
val ys: ValidationNel[String, List[Int]] = List(1, 2, 3).success
val zs: ValidationNel[String, List[Int]] = List(4, 5).success
We can lift the list concatenation function (++
) into the Validation
like this:
scala> println((ys |@| zs)(_ ++ _))
Success(List(1, 2, 3, 4, 5))
scala> println((xs |@| ys)(_ ++ _))
Failure(NonEmptyList(Error!))
scala> println((xs |@| xs)(_ ++ _))
Failure(NonEmptyList(Error!, Error!))
This syntax is a little weird—it's very unlike how you lift functions into an applicative functor in Haskell, for example, and is designed this way primarily to outsmart Scala's fairly stupid type inference system. See my answer here or blog post here for more discussion.
One part of the weirdness is that xs |@| ys
doesn't really mean anything on its own—it's essentially an argument list that's waiting to be applied to a function that it will lift into its applicative functor and apply to itself.
The +++
on Validation
is a much simpler kind of creature—it's just the addition operation for the Semigroup
instance for the type (note that you could equivalently use Scalaz's semigroup operator |+|
here in place of +++
). You give it two Validation
results with matching semigroup types and it gives you another Validation
—not some awful ApplyOps
thing.
As a side note, in this case the addition operation for Validation
's semigroup is the same as the semigroup operation for the right side lifted into the Validation
:
scala> (xs |+| ys) == (xs |@| ys)(_ |+| _)
res3: Boolean = true
This won't always be the case, however (it's not for \/
, for example, where the semigroup accumulates errors but the applicative functor doesn't).