Suppose I want a generic abstract tree type and then want to specialize it to create specific types of trees. For example I might have:
sealed abstract class AST[T <: AST[T]] {
def child : List[T] ;
}
case class LeafAST[T <: AST[T]]( x : Int ) extends AST[T] {
def child = Nil
}
case class BranchAST[T <: AST[T]]( left : T, right : T ) extends AST[T] {
def child = left :: right :: Nil
}
Now I want a specific version that adds a "type" field to each class. So let's introduce a Typed
trait.
trait Typed { var ty : Type = NoType }
How can I define specialized versions of the three classes AST, BranchAST and LeafAST that have this trait?
First attempt. Use Scala's type member feature. Type members have to be members of something, hence the object definition
object TypedASTObj {
type TypedAST = AST[TypedAST] with Typed ;
type TypedLeafAST = LeafAST[TypedAST] with Typed ;
type TypedBranchAST = BranchAST[TypedAST] with Typed ;
}
This gives an error "illegal cyclic reference involving type TypedAST".
Second attempt. This time I start a new file and put in
abstract sealed trait TypedAST extends AST[TypedAST] with Typed ;
case class TypedLeafAST( override val x : Int ) extends LeafAST[TypedAST](x) with TypedAST{ }
case class TypeBranchAST( override val left : TypedAST, override val right : TypedAST ) extends BranchAST[TypedAST](left, right) with TypedAST { }
But of course this gives an error "illegal inheritance from sealed class AST" because TypedAST extends a sealed class AST that is defined in another file. I don't really want to inherit from AST anyway;2 what I want to do is to specialize it. Inheritance is just a means to the end. (By the way, I'm not really sure that a sealed trait is what I want here anyway. The reason I made it a trait rather than a class is that TypedLeafAST needs to extend both TypedAST and LeafAST.)
I'm using both Scala 2.9.1 and 2.9.2.