Scala:使协变类型不变



我想实现以下功能:

case class ValidatorClean[+A](apply: A => A)
implicit val traversableValidatorClean = ValidatorClean[Traversable[String]](_.map(_.trim))

使得例如每当需要ValidatorClean[Seq[String]]ValidatorClean[List[String]]时就拾取traversableValidatorClean

然而,这并没有编译,错误为

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

我知道函数的输入是反变的,输出是协变的,但我希望Aapply中表现不变。也就是说,apply中的函数将始终返回与其输入完全相同的类型。

这能实现吗?

ValidatorClean协变是没有意义的。

假设你有:

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 = ???
}

通过使ValidatorClean协变,你就是说ValidatorClean[Dog]ValidatorClean[Animal]的一个子类型,这意味着如果你需要ValidatorClean[Animal],你也会接受ValidatorClean[Dog]ValidatorClean[Cat]

假设我们有一个Animal,但我们不知道它是子类型。

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

现在我写:

Animal.validate(unknown)

会发生什么?如果有一个隐含的ValidatorClean[Dog]可用,validate会欣然接受。也许它看起来像:

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

但是,这个接受Dog并调用canBark的函数怎么能同时处理任意的Animal呢?它不能。

类似地,ValidatorClean[Traversable[String]]也会解析为ValidatorClean[Any],即使Any没有map方法,因此它无法工作。

相关内容

  • 没有找到相关文章

最新更新