Scala:隐式转换在任何情况下都有效吗?

Scala:隐式转换在任何情况下都有效吗?,scala,implicit,typeclass,Scala,Implicit,Typeclass,我想将不同类型层次结构中的一些对象存储到List[Any]或类似的容器中,但稍后会对它们执行隐式转换,以执行类似类型类的操作。 以下是一个例子: abstract class Price[A] { def price(a: A): Int } trait Car case class Prius(year: Int) extends Car trait Food case class FriedChicken() extends Food object Def { // implic

我想将不同类型层次结构中的一些对象存储到
List[Any]
或类似的容器中,但稍后会对它们执行隐式转换,以执行类似类型类的操作。 以下是一个例子:

abstract class Price[A] {
  def price(a: A): Int
}

trait Car
case class Prius(year: Int) extends Car
trait Food
case class FriedChicken() extends Food

object Def {
  // implicit object AnyPrices extends Price[Any] {
  //   def price(any: Any) = 0
  // }

  // implicit object PriusPrices extends Price[Prius] {
  //   def price(car: Prius) = 100
  // }

  implicit object CarPrices extends Price[Car] {
    def price(car: Car) = 100
  }

  implicit object FoodPrices extends Price[Food] {
    def price(food: Food) = 5
  }
}

def implicitPrice[A: Price](x: A) = implicitly[Price[A]].price(x)

import Def._  
val stuff: List[Any] = List(Prius(2010), FriedChicken())
stuff map { implicitPrice(_) }
上述代码抛出一个错误,如下所示:

error: could not find implicit value for evidence parameter of type Price[Any]
       stuff map { implicitPrice(_) }
                                ^
如果取消注释
AnyPrices
,您将得到
列表(0,0)
,但这不是我所期望的。 我必须将清单存储到列表中才能工作吗


此外,
List(Prius(2010))map{implicitPrice()}
也不起作用,因为它想要
Price[Prius]
而且
Price[Car]
不够好。有没有办法使它更灵活?

因此,一旦对象减少到
Any
,我就无法获得类型类。我尝试使用
Manifest
也失败了,因为即使我有
Manifest[T]
对象,我似乎也无法将
Any
强制转换为
T

import reflect.Manifest._
def add [A, B >: A](stuff: A, list: List[(B, Manifest[_])])(implicit m: Manifest[A]) = (stuff, m) :: list
val stuff2 = add(Prius(2000), add(FriedChicken(), Nil))
stuff2 map { x =>
  val casted = x._2.erasure.cast(x._1)
  implicitPrice(casted)
}
给我

error: could not find implicit value for evidence parameter of type Price[Any]
因此,似乎我必须先将问题解析为
Price
,然后才能将它们粘贴到
列表中:

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 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) }

隐式是静态选择的。考虑到您的列表包含不相关的类型,它的静态类型是
list[Any]
,这说明了您看到的行为。您能建议一些解决方法吗
Manifest[]#erasure.cast也返回
Any
。有两件事:1)我对列表的推断类型有误。它实际上是
List[Price]
,但您明确地将
stuff
键入为
List[Any]
;2) 底线是隐式是一个静态解析的构造,而您需要任何给定产品的价格确定方法的动态解析。我建议使用trait/mix-in方法。即使可以使用隐式转换,推断的类型似乎是
List[Product]
res0:List[Product]=List(普锐斯(2010),FriedChicken())
。因为我可以存储比
Product
更低的类型,比如
String
,所以我强制执行
Any
,但这似乎并不重要,因为它只适用于类型,而不适用于超类型。