type のすべてのサブタイプで機能する汎用の暗黙的なコンバーターを定義したいと思いますT
。例えば:
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
}
関連: