简体   繁体   中英

Scala: Make covariant type invariant

I would like to achieve the following functionality:

case class ValidatorClean[+A](apply: A => A)

implicit val traversableValidatorClean = ValidatorClean[Traversable[String]](_.map(_.trim))

so that traversableValidatorClean gets picked whenever a ValidatorClean[Seq[String]] or ValidatorClean[List[String]] is needed, for example.

However, this doesn't compile, with the error

covariant type A occurs in contravariant position in type => A => A of value apply

I understand that a function is contravariant in its input and covariant in its output, but I want A to behave invariantly in apply . That is, the function in apply will always return the exact same type as its input.

Can this be achieved?

It doesn't make sense for ValidatorClean to be covariant.

Lets say you have:

abstract class Animal

object Animal {
    def validate[A <: Animal : ValidatorClean](animal: A): Animal =
        implicitly[ValidatorClean[A]].apply(animal)
}

class Cat {
    def canMeow: Boolean = ???
}

class Dog {
    def canBark: Boolean = ???
}

By making ValidatorClean covariant, you're saying that ValidatorClean[Dog] is a sub-type of ValidatorClean[Animal] , which means that if you need a ValidatorClean[Animal] , you will also accept a ValidatorClean[Dog] or ValidatorClean[Cat] for that matter.

So let's suppose we have an Animal , but we don't know it's sub-type.

 val unknown: Animal = new Dog // perhaps the Animal really came from a List

Now I write:

Animal.validate(unknown)

What happens? If there is an implicit ValidatorClean[Dog] available, validate will gladly accept it. Perhaps it looks like:

implicit validateDog = ValidatorClean[Dog](dog => if (dog.canBark) dog else ???)

But how can this function that accepts a Dog and calls canBark also process an arbitrary Animal ? It can't.

Similarly, a ValidatorClean[Traversable[String]] would also resolve for a ValidatorClean[Any] , even though Any does not have a map method, so it cannot work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM