0

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.

Theodore Norvell
  • 15,366
  • 6
  • 31
  • 45
  • 1
    What do you mean by "specialize" the type? How do you intend to use it? – Daniel C. Sobral Oct 16 '11 at 05:30
  • Specialize as in to create nongeneric types from generic types. For example SeqInt is a specialization of Seq if you declare `type SeqInt = Seq[Int]`. Unfortunately because of circularity, the compiler does not like my first attempt, which is along this line. The "second attempt" almost works if you remove the sealed keyword from AST. The problems then are (a) that one loses the warnings when cases are missing and (b) the sealed keyword on TypedAST does not have the desired effect of creating warnings for missing cases. – Theodore Norvell Oct 16 '11 at 17:05
  • 1
    Take a look into Shapeless, on the next link you can find a good example for generic trees: https://books.underscore.io/shapeless-guide/shapeless-guide.html#sec:labelled-generic If I have time I'll to prepare an example – Carlos Verdes Jun 15 '20 at 18:48

0 Answers0