scala - Scalaz Validation with applicative functor |@| not working -
i'm trying use scalaz 7 validation in app. however, i'm having issue getting |@|
applicative functor coalesce failures. here's code have:
type validationresult = validationnel[string, unit] def validate[a: classtag](instance: a, fieldnames: option[seq[string]] = none): validationresult = { val fields = classtag[a].runtimeclass.getdeclaredfields val fieldsubset = fieldnames match { case some(names) => fields.filter { field => names.contains(field.getname) } case none => fields } fieldsubset.map { field => field.getannotations.toseq.map { field.setaccessible(true) val (name, value) = (field.getname, field.get(instance)) field.setaccessible(false) annotation => annotation match { case min: min => minvalidate(name, value, min.value()) case size: size => sizevalidate(name, value, size.min(), size.max()) } } }.flatten[validationresult].foldleft(().successnel[string])(_ |@| _) }
the minvalidate
, sizevalidate
functions return validationresults
.
the problem is, code won't compile. error message is:
type mismatch, expected f0.type#m[notinferedb], actual: validationresult
i have no idea means... need give scala more type info?
what i'm trying accomplish is, if fields successnel
s, return that, otherwise, return combination of failurenel
s.
has |@|
changed since previous version of scalaz? because if like:
().successnel |@| ().successnel
i same error.
update
i started poking around scalaz source , found +++
seems want.
what's difference between +++
, |@|
?
scalaz's applicative builder syntax (|@|
) gives way of "lifting" functions applicative functor. suppose have following results, 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 list concatenation function (++
) validation
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 little weird—it's unlike how lift functions applicative functor in haskell, example, , designed way outsmart scala's stupid type inference system. see my answer here or blog post here more discussion.
one part of weirdness xs |@| ys
doesn't mean on own—it's argument list that's waiting applied function lift applicative functor , apply itself.
the +++
on validation
simpler kind of creature—it's addition operation semigroup
instance type (note equivalently use scalaz's semigroup operator |+|
here in place of +++
). give 2 validation
results matching semigroup types , gives validation
—not awful applyops
thing.
as side note, in case addition operation validation
's semigroup same semigroup operation right side lifted validation
:
scala> (xs |+| ys) == (xs |@| ys)(_ |+| _) res3: boolean = true
this won't case, (it's not \/
, example, semigroup accumulates errors applicative functor doesn't).
Comments
Post a Comment