object Compiler1 { // Base implementation: constants + eval trait Base { type E <: Exp trait Exp { def eval: Int } trait Num extends Exp { def value: Int def eval = value } } // Add 'Add' expressions to the base. trait BaseAdd extends Base { type E <: Exp trait Exp extends super.Exp trait Add extends Exp { def left: E def right: E def eval = left.eval + right.eval } } // Add a 'show' operation to the base. trait Show extends Base { type E <: Exp trait Exp extends super.Exp { def show: String } trait Num extends super.Num with Exp { def show = value.toString } } // Compose the 'Add' and 'Show' extensions. trait ShowAdd extends BaseAdd with Show { type E <: Exp // Inheritance hierarchy plumbing. trait Exp extends super[BaseAdd].Exp with super[Show].Exp trait Num extends Exp with super[BaseAdd].Num with super[Show].Num trait Add extends Exp with super[BaseAdd].Add { def show = left.show + " + " + right.show } } // Tie the knot object C extends ShowAdd { type E = Exp case class Num(value: Int) extends super.Num case class Add(left: Exp, right: Exp) extends super.Add } def main(args: Array[String]) = { import C._ val t = Add(Num(3), Num(4)) println(t.show + " --> " + t.eval) } }