3

我使用從屬方法類型和編譯器(2.10.0.r26005-b20111114020239)的每晚構建試圖抽象case類的模塊中進行匹配。我從Miles Sabin' example發現了一些靈感。模式的抽象case類

我真的不明白什麼是錯在下面的(自足)代碼。輸出取決於foo中的模式順序。

// afaik, the compiler doesn't not expose the unapply method 
// for a companion object 
trait Isomorphic[A, B] { 
    def apply(x: A): B 
    def unapply(x: B): Option[A] 
} 

// abstract module 
trait Module { 
    // 3 types with some contraints 
    type X 
    type Y <: X 
    type Z <: X 
    // and their "companion" objects 
    def X: Isomorphic[Int, X] 
    def Y: Isomorphic[X, Y] 
    def Z: Isomorphic[Y, Z] 
} 

// an implementation relying on case classes 
object ConcreteModule extends Module { 
    sealed trait X { val i: Int = 42 } 
    object X extends Isomorphic[Int, X] { 
    def apply(_s: Int): X = new X { } 
    def unapply(x: X): Option[Int] = Some(x.i) 
    } 
    case class Y(x: X) extends X 
    // I guess the compiler could do that for me 
    object Y extends Isomorphic[X, Y] 
    case class Z(y: Y) extends X 
    object Z extends Isomorphic[Y, Z] 
} 

object Main { 
    def foo(t: Module)(x: t.X): Unit = { 
    import t._ 
    // the output depends on the order of the first 3 lines 
    // I'm not sure what's happening here... 
    x match { 
     // unchecked since it is eliminated by erasure 
     case Y(_y) => println("y "+_y) 
     // unchecked since it is eliminated by erasure 
     case Z(_z) => println("z "+_z) 
     // this one is fine 
     case X(_x) => println("x "+_x) 
     case xyz => println("xyz "+xyz) 
    } 
    } 
    def bar(t: Module): Unit = { 
    import t._ 
    val x: X = X(42) 
    val y: Y = Y(x) 
    val z: Z = Z(y) 
    foo(t)(x) 
    foo(t)(y) 
    foo(t)(z) 
    } 
    def main(args: Array[String]) = { 
    // call bar with the concrete module 
    bar(ConcreteModule) 
    } 
} 

有什麼想法嗎?

+0

我只是試着用最新的主幹,它不編譯我:35:錯誤:非法依賴方法類型。使用2.10.0.r26037-b20111121020211。這可能不是爲了工作? –

+0

剛剛使用2.10.0.r26037-b20111121020211進行了測試,併爲我編譯。我複製粘貼整個塊,然後'Main.main(Array())'。 – betehess

回答

1

的警告是正確的,是因爲預期,從內fooYZ都將被擦除其範圍,即查看。 X

更重要的是奇怪的是,無論是對陣Y或反對Z阻撓對陣X,即比賽的存在。在這種情況下,

def foo(t: Module)(x: t.X): Unit = { 
    import t._ 
    // the output depends on the order of the first 3 lines 
    // I'm not sure what's happening here... 
    x match { 
    // unchecked since it is eliminated by erasure 
    // case Y(_y) => println("y "+_y) 
    // unchecked since it is eliminated by erasure 
    // case Z(_z) => println("z "+_z) 
    // this one is fine 
    case X(_x) => println("x "+_x) 
    case xyz => println("xyz "+xyz) 
    } 
} 

結果是,

x 42 
x 42 
x 42 

這似乎是合理的,而具有恢復早先的比賽之一,

def foo(t: Module)(x: t.X): Unit = { 
    import t._ 
    // the output depends on the order of the first 3 lines 
    // I'm not sure what's happening here... 
    x match { 
    // unchecked since it is eliminated by erasure 
    case Y(_y) => println("y "+_y) 
    // unchecked since it is eliminated by erasure 
    // case Z(_z) => println("z "+_z) 
    // this one is fine 
    case X(_x) => println("x "+_x) 
    case xyz => println("xyz "+xyz) 
    } 
} 

結果是,

xyz [email protected] 
y [email protected] 
xyz Z(Y([email protected])) 

這不:我不能看到什麼好的理由額外的情況下會導致xyz被選擇過X,所以我認爲你碰到的模式匹配的錯誤。我建議你在Scala JIRA中搜索類似的問題,如果你找不到,可以打開一個票據,上面提供了一個最小化的重現示例。

要在上面的第二個例子誠實,我會預期已經所有三個拜實例中被選擇的情況下YY正被擦除到XY前述情況中匹配表達式的X情況。但我們在這裏沒有受到限制的領域,我並不是對自己的直覺充滿信心。