Scalaz Validation with applicative functor |@| not working

前端 未结 1 1580
南笙
南笙 2021-01-02 22:09

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

相关标签:
1条回答
  • 2021-01-02 23:01

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

    0 讨论(0)
提交回复
热议问题