2013-10-30 50 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]] 
    } 

這使得它編譯。只是我沒有很積極的想繼續構建這個結構,如果它即將崩潰:-(