2017-05-15 1 views
11

암시 적 변환이 한 케이스에서는 정확히 작동하지만 다른 케이스에서는 작동하지 않는 이유를 이해하려고합니다. 기본적으로, 나는 Option[T]에서 Option[Wrapper[T]]에 암시 적 변환이 있고, 암시 적으로 포장됩니다 선택적 문자열을 반환하는 함수를 정의하려고암시 적 변환 이상함

case class Wrapper[T](wrapped: T) 
    trait Wrapping { implicit def wrapIt[T](x: Option[T]) = x.map(Wrapper(_)) 

    class NotWorking extends Wrapping { def foo: Option[Wrapper[String]] = Some("foo") } 

    class Working extends Wrapping { 
     def foo: Option[Wrapper[String]] = { 
     val why = Some("foo") 
     why 
     } 
    } 

: 다음은 예입니다.

질문은 왜 Option[String] (NotWorking 위)을 반환하려고 할 때 오류 (found : String("foo") required: Wrapper[String])가 표시됩니다. 결과를 반환하기 전에 val에 결과를 할당하면 사라집니다.

무엇을 제공합니까?

답변

10

이것이 의도 된 것인지 또는 버그로 간주 될지 모르지만 여기에 제가 생각하는 것이 있습니다.

def foo: Option[Wrapper[String]] = Some("foo")에서 컴파일러는 Some()으로 제공된 인수의 예상 유형을 Wrapper[String]으로 설정합니다. 그런 다음 예상 한 내용이 아닌 String을 제공 했으므로 암시 적 변환 String => Wrapper[String]을 찾고 찾을 수 없으며 실패합니다.

가 왜 형의 물건을 예상, 단지 변환을 찾을 이후 시도 Some[String]Some("foo")를 입력하지 않습니다 필요합니까? 이 코드가 작동하려면 다음 컴파일이 Invariant[String]으로 실패하기 때문에, 컴파일러는 단지 Invariant[String]Invariant("s") 입력 할 수 없습니다 위해

case class Invariant[T](t: T) val a: Invariant[Any] = Invariant("s") 

이의 하위 유형 아니다

: 는 scalac 다음 코드 유형 체킹 할 수 싶어하기 때문에 Invariant[Any]. 컴파일러는 "s"의 예상 유형을 Any으로 설정하여 "s"이 너무 늦기 전에 Any의 인스턴스임을 확인해야합니다.

이 코드와 코드가 올바르게 작동하려면 컴파일러에 좋은 이유가있는 것처럼 보이지 않는 일종의 역 추적 논리가 필요할 것이라고 생각합니다.

Working 코드가 작동하는 이유는 이러한 유형의 유추가 여러 줄에 걸쳐 있지 않기 때문입니다. 유사하게 val a: Invariant[Any] = {val why = Invariant("s"); why}이 아니고이 컴파일됩니다.