ここでLandeiからMyType トリックを借りました。しかし最近、私は自己タイプの問題に遭遇しました。例は私が何を意味するかを示しています:
trait Excitable[SELF] { self: SELF =>
def withMoreAnger: SELF
}
trait Animal[SELF0] { self: SELF0 =>
type SELF = SELF0 // to reveal SELF0 for method spitAt used as a dependent method type
type SpittableAnimal[S] <: Animal[S]
def spitAt[A <: SpittableAnimal[_]](a: A): a.SELF
}
trait ExcitableAnimal[SELF] extends Animal[SELF] with Excitable[SELF] { self: SELF =>
type SpittableAnimal[S] = ExcitableAnimal[S]
def spitAt[A <: SpittableAnimal[_]](a: A): a.SELF = a.withMoreAnger
}
trait Quadruped[SELF] extends ExcitableAnimal[SELF] { self: SELF => }
case class Dog(anger: Int) extends Quadruped[Dog] {
def withMoreAnger: Dog = copy(anger = anger + 1)
}
case class Cat(anger: Int) extends Quadruped[Cat] {
def withMoreAnger: Cat = copy(anger = anger + 1)
}
val dog = Dog(anger = 0)
val cat = Cat(anger = 0)
val angryCat: Cat = dog spitAt cat // fine
val anotherDog = Dog(0)
val animals = Seq(dog, cat)
val angryAnimals: Seq[Quadruped[_]] = for (a <- animals) yield anotherDog spitAt a // fine
val veryAngryAnimals: Seq[Quadruped[_]] = for (a <- angryAnimals) yield anotherDog spitAt a // type mismatch !!!
私がそれを明らかにすることができる限り、問題は、spitAt
メソッドのアンダースコアが最終的Any
にfora.SELF
を生成することであるように思われます。しかし、どうすればこのコードを機能させることができますか?
私もこれを試しました:
def spitAt[A <: SpittableAnimal[A]](a: A): A = a.withMoreAnger
しかし、推論された型引数は、メソッドspitAtの型パラメーターの境界に準拠していません。これは、上の要素または以下の要素の型引数が、SELF
少なくともanimals
、に_ >: Cat with Dog <: Quadruped[_]
準拠していないため、私には明らかです。a.SELF
A
spitAt
A
spitAt
def spitAt[A <: SpittableAnimal[S], S <: A](a: A): A = a.withMoreAnger
では、 -loop行を機能spitAt
させるためのメソッドの正しいシグネチャは何ですか?
おそらく、SELFタイプパラメータの分散アノテーション()が役立つかもしれませんが、その方法はわかりません。for
+SELF