如何在节点之间强制执行图形类型

时间:2012-11-08 16:53:55

标签: scala

我试图在节点与其父节点之间的图形中强制实施类型关系。 我有以下不能编译child.parents :: = this。 任何评论都会受到欢迎

  trait TGraphNode {
    type NodeType <: TGraphNode
    var id = -1
    var parents = List[NodeType]()
    var children = List[TGraphNode]()

    def addChild(child: NodeType) {
      children ::= child
      child.parents ::= this
    }

    override def toString = "node-"+id+"->"+children
  }

抱歉 - 下次会添加编译错误。我试图实现以下目标:想象我有2个类型为F和C的节点 - 我想通过构造强制执行C只能将F作为父级,但是,反过来我不在乎。 F可以有C,D ..作为孩子。所以我想捕获可以在实现特征的类中覆盖ParentType。

class F extends TGraphNode ...
class B extends TGraphNode {
  type ParentType = F
}

由于

2 个答案:

答案 0 :(得分:2)

错误消息是

error: Type mismatch 
 found   : TGraphNode.this.type (with underlying type TGraphNode)
 required: child.NodeType
             child.parents ::= this

(请不要在你的问题中省略)

您的代码声明节点可以选择其父项所需的类型,类型为变量NodeType。这种类型必须符合TGraphNode,但它可能比这更受限制。

鉴于此,child中添加的addChild可能需要比this更为受限的类型作为其父级。编译器拒绝这一点是正确的。

这是错误消息所说的内容: 您将this放在子项的父级列表中。 this的类型为TGraphNode。 但是parents列表是孩子NodeType的列表(child.NodeType) 没有保证比类型匹配。

如果你不解释你想要实现的目标,我不能进一步评论。


编辑后:

您必须声明您将在addChild中仅接受将其接受为父级的子级。这可能有点棘手,这可能是一种方式:

def addChild[N](child: TGraphNode{type NodeType = N})
               (implicit thisAsParentOfChild : this.type <:< N) {
  children ::= child
  child.parents ::= thisAsParentOfChild(this)
}

完成后,你现在可以做

class F extends TGraphNode {type NodeType = TGraphNode }
class C extends TGraphNode {type NodeType = F }
class X extends TGraphNode {type NodeType = TGraphNode } 

val f = new F
val c = new C
val x = new X

f.addChild(c) // ok 
x.addChild(f) // ok

x.addChild(c) // error: Cannot prove that x.type <:< F

如果您不知道类型为&lt;:&lt;的隐式参数是什么的确看看What do <:<, <%<, and =:= mean in Scala 2.8, and where are they documented?


在第二次思考和阅读bluenote建议时,在你的语境中写addParentaddChild更简单(我相信这是扭转孩子和父母的正确方法):

def addParent(parent: NodeType) {
  parents ::= parent
  parent.children ::= this
} 

答案 1 :(得分:1)

我的猜测是,您只是混淆了NodeTypeTGraphNode类型。如果我理解正确,孩子可能属于TGraphNode的子类型。至少这是addChild函数签名所指示的,并且可能是更可能的用例。因此,孩子必须是NodeType类型,但父母可以有更一般的TGraphNode类型,即:

trait TGraphNode {
  type NodeType <: TGraphNode
  var id = -1
  var children = List[NodeType]()
  var parents = List[TGraphNode]()

  def addChild(child: NodeType) {
    children ::= child
    child.parents ::= this
  }

  override def toString = "node-"+id+"->"+children
}

修改

好的,你真的想要它反过来。由于上面提到的版本编译,你可以反转孩子和父母的定义,以获得你想要的。