Generics 专门化通用密封类型。第一部分

Generics 专门化通用密封类型。第一部分,generics,scala,types,sealed,Generics,Scala,Types,Sealed,假设我想要一个通用的抽象树类型,然后想要专门化它来创建特定类型的树。例如,我可能有: 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,

假设我想要一个通用的抽象树类型,然后想要专门化它来创建特定类型的树。例如,我可能有:

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
}
如何定义具有此特性的三个类AST、BranchAST和LeafAST的专用版本

第一次尝试。使用Scala的类型成员功能。类型成员必须是某个对象的成员,因此对象定义

object TypedASTObj {
    type TypedAST = AST[TypedAST] with Typed ;
    type TypedLeafAST = LeafAST[TypedAST] with Typed ;
    type TypedBranchAST = BranchAST[TypedAST] with Typed ;
}
这会产生一个错误“非法循环引用,涉及类型TypedAST”

第二次尝试。这一次,我开始一个新文件并放入

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 { }
但这当然会产生一个错误“从密封类AST非法继承”,因为TypedAST扩展了另一个文件中定义的密封类AST。我真的不想从AST继承遗产;我想做的是使它专业化。继承只是达到目的的一种手段。(顺便说一句,我不确定密封的trait是否是我想要的。我之所以将其作为trait而不是类,是因为TypedLeafAST需要同时扩展TypedAST和LeafAST。)


我同时使用Scala 2.9.1和2.9.2。

您所说的“专门化”类型是什么意思?您打算如何使用它?专门化为从泛型类型创建非泛型类型。例如,如果您声明
类型SeqInt=Seq[Int]
,则SeqInt是Seq的专门化。不幸的是,由于循环性,编译器不喜欢我的第一次尝试,这是沿着这条路线进行的。如果从AST中删除sealed关键字,“第二次尝试”几乎有效。接下来的问题是(a)当案例丢失时会丢失警告,以及(b)TypedAST上的sealed关键字没有为丢失的案例创建警告的预期效果。看看Shapess,在下一个链接中,你可以找到一个通用树的好例子:如果我有时间,我将准备一个例子
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 { }