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 successnels, return that, otherwise, return combination of failurenels.
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