В случае ковариантных / контравариантных типов вам почти необходимо определить класс типов для «базового» типа здесь:
implicit object FruitWriter extends Writer[Fruit] {
def write(a : Fruit) = a match {
case _ : Apple => println("I am an apple!")
case _ : Orange => println("I am an orange")
}
}
Вы также можете работать над определением класса типов с дисперсией, чтобыWriter [Fruit] можно использовать, когда вам нужен Writer [Apple].К сожалению, но если вы хотите использовать ОО-полиморфизм, вы должны закодировать его в функциональные аспекты.
* сильный текст * Другой вариант - использовать HList для записи плодов ивыполнить всю типовую рекурсию самостоятельно ...
Предполагая:
trait HList
object HNil extends HList
case class ::[A, Rest <: HList](head : A, tail : Rest)
Тогда мы можем сделать что-нибудь веселое, например:
implicit def nilWriter = new Writer[HNil] = { def write(o : HNil) = () }
implicit def hlistWriter[A, Rest](implicit aw : Writer[A], rw : Writer[Rest]) =
new Writer[A :: Rest] {
def write(o : (A :: Rest)) = {
aw.write(o.head)
rw.write(o.tail)
}
}
СЕЙЧАС
write( new Orange :: new Apple :: HNil)
Примечание. Я не тестировал этот код, но концепция рекурсивно охватывающих типов является разумной.Я на самом деле не рекомендую этот подход.