2013-10-30 26 views
0

我正在定义一个通用的树结构,即可以扩展的一个例子,以便例如分支和叶子包含附加值(例如,我需要添加一个名称字符串)。解决令人讨厌的模式匹配问题

所以它看起来像这样:

trait TreeNodes { 
    val Node    = Either 
    type Node[+B, +L]  = Either[B, L] 
    val IsBranch   = Left 
    type IsBranch[+B, +L] = Left[B, L] 
    val IsLeaf   = Right 
    type IsLeaf[+B, +L] = Right[B, L] 
} 

object TreeLike extends TreeNodes { 
    trait BranchLike[Elem, B, L] { 
    type N = Node[B, L] 

    def iterator: Iterator[N] 
    } 

    trait LeafLike[Elem] { 
    def value: Elem 
    } 
} 
trait TreeLike[Elem, Repr] { 
    type Leaf <: TreeLike.LeafLike[Elem] 
    type Branch <: TreeLike.BranchLike[Elem, Branch, Leaf] 

    def root: Branch 
} 

不幸的是,有一个模式匹配错误:

def test[Elem, T <: TreeLike[Elem, T]](tree: T): Unit = { 
    import TreeLike.{IsLeaf, IsBranch} 

    def printLeaves(b: T#Branch): Unit = b.iterator.foreach { 
    case IsLeaf(l) => println(l.value) 
    case IsBranch(c) => printLeaves(c) 
    } 

    printLeaves(tree.root) 
} 

错误如下:

[error]   during phase: patmat 
[error]  library version: version 2.10.3 
[error]  compiler version: version 2.10.3 
... 
[error] symbol definition: case val x1: b.N 
[error]     tpe: b.N 
[error]  symbol owners: value x1 
[error]  context owners: value x0$1 -> value $anonfun -> method printLeaves -> 
    method test -> object Voodoo -> package typerbug 
... 
[error] no-symbol does not have an owner 

我怀疑patmat有以某种方式与T#Branch麻烦。任何想法如何在这里解决?

我也不是100%满意的包装叶子和树枝在Either。这是必要的,因为当我试图定义一个超类型的LeafLikeBranchLike,并弄清楚如何在实现中正确地使用子类型,并且模式匹配打破了,因为我没有弄清楚得到正确的提取器。所以也许使用Either这不是一个坏主意吗?

+0

使用Scala 2.11.0-M6编译器不会崩溃... –

+0

我想你会看到[SI- 7891](https://issues.scala-lang.org/browse/SI-7891),并且有一个很长的错误列表:/ –

+0

@SRI有趣......那张票并不是说它是在2.11.0-M6中解决,但我应该附上我的例子 –

回答

0

类型别名N是一个“问题”(WTF)。

trait BranchLike[Elem, B, L] { 
    def iterator: Iterator[Node[B, L]] 
    } 

这使得它编译。只是我没有很积极的想继续构建这个结构,如果它即将崩溃:-(