Reputation: 5023
I have this implementation of scalaz Validation, it seems like that implicitly scalaz.Bind not in the scope, so for expression is not working. Here is the code:
import scalaz._
import Scalaz._
case class User(name: String, knowScala: Boolean, age: Int)
object PublicValidationSpec extends BasicValidation {
def validate(user: User): Validation[String, String] = {
for {
b <- checkAge(user)
c <- checkName(user)
} yield s"Congrats, ${c.name}"
}
}
trait BasicValidation {
def checkName(user: User): Validation[String, User] = {
if(user.name == "") "must have a name".fail else user.success
}
def checkAge(user: User): Validation[String, User] = {
if(user.age < 3) "must be a valid age".fail else user.success
}
}
the exception is
Error:(14, 25) Implicit not found: scalaz.Unapply[scalaz.Bind,
scalaz.Validation[String,scalaz.validation.User]]. Unable to unapply type
`scalaz.Validation[String,scalaz.validation.User]` into a type constructor of
kind `M[_]` that is classified by the type class `scalaz.Bind`. Check that the
type class is defined by compiling `implicitly[scalaz.Bind[type constructor]]` and
review the implicits in object Unapply, which only cover common type 'shapes.'
b <- checkAge(user)
Did i miss some implicit imports here ?
^
Upvotes: 4
Views: 622
Reputation: 2913
Validation does not have a Bind defined for it.
In Scalaz 7.1.0-M5 (M6 too) Validation.flatMap
is deprecated and in an attempt at subverting the warning, it looks like the precedence of flatMap
is losing to scalaz.syntax.bind._
, which is part of the Scalaz._
import. See this commit https://github.com/scalaz/scalaz/commit/2727b2451eba2aa159f3fbb62bf92790ac99dc7a. Try adding import scalaz.Validation.FlatMap._
or importing only the things you need, e.g.
import scalaz.Validation
import scalaz.syntax.validation._
I would recommend using something besides Validation
though, as this will probably only cause you more problems in the future. See scalaz.\/
below.
This does compile with scalaz 7.0.5. Validation.flatMap
is defined in 7.0.6 so it should compile with that version too. I would not use this functionality (Validation
in for
comprehensions) in new code though.
The scalaz powers that be have gona back and forth on deprecating Validation.flatMap
for some time now. flatMap
is what allows it to work in for
comprehensions. flatMap
is deprecated in the working branch though. There is a long background on this. See https://groups.google.com/forum/#!topic/scalaz/Wnkdyhebo2w.
TLDR - Validation is not a monad. Any possible implementation of Validation.flatMap
will not match behavior of the Apply
defined for Validation
.
Use scalaz.\/
(a.k.a. disjunction) if you want to use something in for
comprehensions. If you need to accumulate errors, the reason to use Validation
over \/
, convert to Validation
and then back to \/
.
Upvotes: 6