【问题标题】:Scala: Do implicit conversions work on Any?Scala:隐式转换是否适用于 Any?
【发布时间】:2010-10-02 06:47:45
【问题描述】:

我想将一些来自不同类型层次结构的对象存储到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,您会得到 List(0,0),但这不是我所期望的。 我是否必须将清单存储到列表中才能正常工作?

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

【问题讨论】:

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

标签: scala implicit typeclass


【解决方案1】:

所以,一旦对象减少到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,然后才能将它们放入List

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 2014-01-22
    • 1970-01-01
    相关资源
    最近更新 更多