I'm not sure I understand why you need a dedicated UserValidator
class in the first place. In a case like this I'd be more likely to bundle all of my generic validation code into a separate trait, and to have my User
companion object (or whatever other piece I want to be responsible for creating User
instances) extend that trait. Here's a quick sketch:
import scalaz._, Scalaz._
trait Validator[E] {
def checkNonEmpty(error: E)(s: String): ValidationNel[E, String] =
if (s.isEmpty) error.failNel else s.successNel
}
sealed trait UserCreationFailure
case object EmptyPassword extends UserCreationFailure
case object EmptyUsername extends UserCreationFailure
case class User(name: String, pass: String)
object User extends Validator[UserCreationFailure] {
def validated(
name: String,
pass: String
): ValidationNel[UserCreationFailure, User] = (
checkNonEmpty(EmptyUsername)(name) |@| checkNonEmpty(EmptyPassword)(pass)
)(apply)
}
And then:
scala> println(User.validated("", ""))
Failure(NonEmptyList(EmptyUsername, EmptyPassword))
scala> println(User.validated("a", ""))
Failure(NonEmptyList(EmptyPassword))
scala> println(User.validated("", "b"))
Failure(NonEmptyList(EmptyUsername))
scala> println(User.validated("a", "b"))
Success(User(a,b))
If you have a huge amount of User
-specific validation logic that you don't want polluting your User
object, I suppose you could factor it out into a UserValidator
trait that would extend your generic Validator
and be extended by User
.