패턴 매칭에서 메소드의 타입 추론과 클래스 타입 파라미터의 차이점


9

유형 매개 변수가 둘러싸는 클래스가 아닌 둘러싸는 메서드에서 올 때 패턴 일치가 다르게 작동하는 이유는 무엇입니까? 예를 들어

trait Base[T]
case class Derived(v: Int) extends Base[Int]

class Test[A] {
  def method(arg: Base[A]) = {
    arg match {
      case Derived(_) => 42
    }
  }
}

오류를 준다

constructor cannot be instantiated to expected type;
 found   : A$A87.this.Derived
 required: A$A87.this.Base[A]
      case Derived(_) => 42
           ^

A메소드 유형 매개 변수 인 경우 성공적으로 컴파일되는 동안

class Test {
  def method[A](arg: Base[A]) = {
    arg match {
      case Derived(_) => 42
    }
  }
}

이 질문은 다니엘의 분석을 바탕으로 합니다 하며 비슷한 질문 에 대한 답변 을 제공하려고 시도했습니다 .

답변:


4

100 % 완전한 답변은 없지만 충분한 포인터가 있습니다.

스칼라 컴파일러는 GADT (Generalized Algebraic Data Types)를 매우 특정한 방식으로 처리합니다. 일부 사례는 특수 처리로 해결되고 일부 사례는 해결되지 않습니다. 도티는 구멍의 대부분을 채우기 위해 노력하고 있으며, 이미 한 해결 하지만 여전히 꽤있다, 관련 문제를 많이 개방 것뿐만 아니라.

Scala 2 컴파일러의 특수 GADT 처리에 대한 일반적인 예는 사용 사례와 매우 관련이 있습니다. 우리가 살펴보면 :

def method[A](arg: Base[A]) = {
  arg match {
    case Derived(_) => 42
  }
}

그리고 반환 유형을 다음과 같이 명시 적으로 선언합니다 A.

def method[A](arg: Base[A]): A 

잘 컴파일됩니다. IDE가 불만을 제기 할 수 있지만 컴파일러가이를 통해 알려줍니다. 메서드는를 반환 A하지만 패턴 일치 사례는 Int이론적으로 컴파일해서는 안되는 로 평가됩니다 . 그러나 컴파일러에서 GADT를 특수하게 처리하면 특정 패턴 일치 분기 A가 "고정"되어 Int있기 때문에 문제가 없다고 말합니다 .Derived 이는이다 Base[Int]).

GADT의 일반 유형 매개 변수 (이 경우 A)는 어딘가에 선언해야합니다. 흥미로운 부분 특수 컴파일러 처리 는 엔 클로징 메소드의 유형 매개 변수로 선언 된 경우에만 작동합니다 . 그것이 포함하는 특성 / 클래스의 유형 멤버 또는 유형 매개 변수에서 오는 경우 직접 목격 한 것처럼 컴파일되지 않습니다.

이것이 100 % 완전한 답변이 아니라고 말한 이유입니다.이 문서를 올바르게 문서화하는 구체적인 장소 (예 : 공식 사양)를 가리킬 수 없습니다. 스칼라에서 GADT를 다루는 소스는 가지 블로그 포스트로 나옵니다. 블로그 포스트 는 그 이상이지만, 그 이상을 원한다면 컴파일러 코드를 직접 파헤쳐 야합니다. 나는 그것을 정확하게 시도했지만 이것이이 방법에 달려 있다고 생각 하지만, 실제로 더 깊이 가고 싶다면 Scala 컴파일러 코드베이스에 더 많은 경험이있는 사람을 핑하고 싶을 수도 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.