3

종속 메서드 형식과 야간 컴파일러 (2.10.0.r26005-b20111114020239) 빌드를 사용하여 모듈의 사례 클래스를 추상화하려고합니다. Miles Sabin' example에서 영감을 얻었습니다.추상화 된 사례 클래스에 대한 패턴 일치

아래 (자체 포함) 코드의 내용을 이해하지 못합니다. 출력은 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

foo에서 보았을 때 YZ은 모두 경계에서 지워지므로 경고가 정확하고 예상됩니다. 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])) 
, 복원 된 이전의 일치 하나, 반면

다음을 제외한 : 나는 할 수 없다. 추가 케이스로 인해 xyzX 이상으로 선택되는 데는 충분한 이유가 있는지 확인하십시오. 패턴 일치 도구에서 버그가 발생했다고 생각합니다. 스칼라 JIRA에서 유사한 문제를 검색해 보시고, 찾을 수 없다면 위에서 추출한 재생 예제를 최소화하여 티켓을여십시오.

은 위의 두 번째 예에서는 솔직히 말해서, 나는 YY 경우 세 개의 인스턴스 덕분에 선택되었다 예상 한 것은 X에 삭제되는과 Y 경우는 일치 식의 X 사건을 선행. 그러나 우리는 여기서 확인되지 않은 영역에 있으며, 나는 나의 직감에 100 % 확신하지 않습니다.