解析超类型的隐式参数
问题描述:
如果为其超类型A定义了隐式,是否可以解析类型B的隐式参数?解析超类型的隐式参数
下面是一个例子:
我有一个可枚举类型类:
trait Enumerable[A] {
def name(a: A): String
def list: List[A]
//... other methods
}
object Enumeration {
def name[A, T >: A](a: A)(implicit ev: Enumerable[T]) = ev.name(a)
def list[T](implicit ev: Enumerable[T]) = ev.list
// ...
}
然后我定义枚举的一个实例:
sealed trait Season
case object Winter extends Season
case object Spring extends Season
case object Summer extends Season
case object Fall extends Season
implicit val seasonEnumerable = new Enumerable[Season] {
override def list: List[Season] = List(Winter, Spring, Summer, Fall)
}
// working :
Enumeration.name(Winter: Season) shouldBe "winter"
// faling :
Enumeration.name(Winter) shouldBe "winter"
Enumeration.name(冬)是,如果失败我不告诉scalac冬天是一个季节。我已经指定'name'方法签名中的隐式参数是A的超类型,但它是不够的...
有没有更好的方法来做到这一点?
答
Eduardo的回答解释了为什么与[A, T >: A]
版本不起作用。但有一个解决问题的简单的解决方案比他给人的:不是引入T
推断的类型参数,介绍它由生存型:
def name[A](a: A)(implicit ev: Enumerable[T >: A] forSome { type T }) = ev.name(a)
或者使用简写,
def name[A](a: A)(implicit ev: Enumerable[_ >: A]) = ev.name(a)
然后编译器只需要决定什么时候寻找ev
就是T
。
答
无论何时您需要推断依赖于类型的类型,这都是常见的不便之处。你的方法
def name[A, T >: A](a: A)(implicit ev: Enumerable[T])
呼吁Winter
时,第一A
会被推断为Winter.type
然后T
为A
,因为它符合该约束,并有在这一点上没有更多的约束。那么编译器当然不会找到Enumerable[Winter.type]
的实例。
有与类型成员虽然一个简单的解决方案:
trait AnyEnumerable {
type E
def name[A <: E](a: A): String
def list: List[E]
}
object Enumeration {
def name[A](a: A)(implicit ev: AnyEnumerable { type E >: A }) = ev.name(a)
def list[T](implicit ev: AnyEnumerable { type E = T }) = ev.list
// ...
}
// an implicit for `Season`
implicit val seasonEnumerable: AnyEnumerable { type E = Season } =
new AnyEnumerable {
type E = Season
def name[A <: Season](a: A): String = a.toString
def list: List[Season] = List(Winter, Spring, Summer, Fall)
}
// compiles!
val zzz = Enumeration.name(Winter)
确实!谢谢:) 你能否解释一下def name [A](a:A)(implicit ev:Enumerable [_>:A])= ev.name(a) 和def name [A,T>: A](a:A)(隐式ev:Enumerable [T])= ev.name(a)? – Loic
我已经扩大了答案。 –