我想定义一个适用于所有类型为T
的子类型的通用隐式转换器。例如:Scala:通用隐式转换器?
abstract class Price[A] {
def price(a: Any): Int
}
trait Car
case class Prius(year: Int) extends Car
trait Food
case class FriedChicken() extends Food
object Def {
implicit def carToPrice[A <: Car](car: A): Price[A] = new Price[A] {
def price(car: Any) = 100
}
implicit def foodToPrice[A <: Food](food: A): Price[A] = new Price[A] {
def price(food: Any) = 5
}
// implicit object PriusPrices extends Price[Prius] {
// def price(car: Any) = 100
// }
//
// implicit object FriedChickenPrices extends Price[FriedChicken] {
// def price(food: Any) = 5
// }
}
import Def._
def add [A, B >: A](stuff: A, list: List[(B, Price[_])])(implicit p: Price[A]) = (stuff, p) :: list
val stuff = add(Prius(2000), add(FriedChicken(), Nil))
stuff map { x => x._2.price(x._1) }
上面的代码抛出一个错误:
error: could not find implicit value for parameter p: Price[FriedChicken]
val stuff = add(Prius(2000), add(FriedChicken(), Nil))
^
我在做什么错?
更新:
由于@extempore指出的,什么是错的是我混乱的隐式转换(查看边界)和上下文范围(包括使用隐含参数)。我的通用隐式转换器没有问题。问题是add
正在使用上下文边界而不是视图。
def add [A, B >: A](stuff: A, list: List[(B, Price[_])])(implicit view: A => Price[A]) = (stuff, view(stuff)) :: list
一个有趣的事情@extempore表明了他的代码是,我们并不真正需要一个通用的转换器,如果Price[A]
是逆变:所以我们可以如下修复它。基本上,我可以让Price[Car]
代表Price[Prius]
工作,这是我想要的。所以,替代背景下必然的版本是:
abstract class Price[-A] {
def price(a: Any): Int
}
implicit object CarPrice extends Price[Car] {
def price(a: Any) = 100
}
implicit object FoodPrice extends Price[Food] {
def price(a: Any) = 1
}
相关:
我想要1)在一次处理中处理类型族的隐式转换2)将支持类型类的各种对象存储在某个容器中并稍后使用它。我没有想到使用反变换,但它是完全合理的,所以'Price [Car]'可以作为'Price [Prius]'。 – 2010-10-02 04:55:20