Suppose one wants to build a novel generic class, Novel[A]
. This class will contain lots of useful methods--perhaps it is a type of collection--and therefore you w
I haven't thought this through fully, but it type checks:
object invariant {
trait Novel[A] {
type Repr[X] <: Novel[X]
def reverse: Repr[A]
def revrev: Repr[A]#Repr[A]
= reverse.reverse
}
class ShortStory[A] extends Novel[A] {
type Repr[X] = ShortStory[X]
def reverse = this
}
val ss = new ShortStory[String]
val ss2: ShortStory[String] = ss.revrev
}
object covariant {
trait Novel[+A] {
type Repr[X] <: Novel[_ <: X]
def reverse: Repr[_ <: A]
def revrev: Repr[_ <: A]#Repr[_ <: A] = reverse.reverse
}
class ShortStory[+A] extends Novel[A] {
type Repr[X] = ShortStory[X]
def reverse = this
}
val ss = new ShortStory[String]
val ss2: ShortStory[String] = ss.revrev
}
EDIT
The co-variant version can be much nicer:
object covariant2 {
trait Novel[+A] {
type Repr[+X] <: Novel[X]
def reverse: Repr[A]
def revrev: Repr[A]#Repr[A] = reverse.reverse
}
class ShortStory[+A] extends Novel[A] {
type Repr[+X] = ShortStory[X]
def reverse = this
}
val ss = new ShortStory[String]
val ss2: ShortStory[String] = ss.revrev
}