2016-11-28 3 views
3

수퍼 유형 A에 암시 적으로 정의 된 경우 유형 B에 대한 암시 적 매개 변수를 해결할 수 있습니까?수퍼 유형에서 암시 적 매개 변수 해결

sealed trait Season 

case object Winter extends Season 
case object Spring extends Season 
case object Summer extends Season 
case object Fall extends Season 

implicit val seasonEnumerable = new Enumerable[Season] { 
    override def list: List[Season] = List(Winter, Spring, Summer, Fall) 
} 

// working : 
Enumeration.name(Winter: Season) shouldBe "winter" 

// faling : 
Enumeration.name(Winter) shouldBe "winter" 

Enumeration.name (겨울) 만약 실패이다

trait Enumerable[A] { 

    def name(a: A): String 

    def list: List[A] 

    //... other methods 
} 

object Enumeration { 
    def name[A, T >: A](a: A)(implicit ev: Enumerable[T]) = ev.name(a) 

    def list[T](implicit ev: Enumerable[T]) = ev.list 

    // ... 
} 

그럼 I 열거 할 인스턴스를 정의 I가 열거 가능한 typeclass이

: 여기

은 일례이며 나는 겨울이 계절이라는 것을 스칼라에게 말하지 않는다. 'name'메소드 서명의 암시 적 매개 변수가 A의 수퍼 유형이지만 충분하지 않다는 것을 지정했습니다 ...

더 좋은 방법이 있습니까?

답변

3

에두아르도의 대답은 설명합니다. 그러나 그가주는 것보다 문제에 대한 간단한 해결책이있다 : 대신, 형식 매개 변수로 T 추론을 도입를 소개 실존 유형의 : 속기를 사용하여,

def name[A](a: A)(implicit ev: Enumerable[T >: A] forSome { type T }) = ev.name(a) 

또는

def name[A](a: A)(implicit ev: Enumerable[_ >: A]) = ev.name(a) 

그렇다면 컴파일러는 ev을 찾을 때만 T이 무엇인지 결정해야합니다.

+0

실제로! 감사합니다 :) def 이름 [A] (a : A) (암시 적 ev : 열거 형 [_] : A) = ev.name (a) 및 def name [A, T> A] (a : A) (암시 적 ev : 열거 가능 [T]) = ev.name (a)? – Loic

+1

답변을 확장했습니다. –

3

유추 할 유형 종속 유형이 필요할 때마다 일반적인 불편 함이 있습니다. 귀하의 방법은

Winter에서 호출
def name[A, T >: A](a: A)(implicit ev: Enumerable[T]) 

먼저 AWinter.type로 추정되며이 그 바인딩을 준수하고 그 시점에서 거기에 더 이상 제약이 있기 때문에 다음 TA합니다. 그럼 물론 컴파일러는 Enumerable[Winter.type]의 인스턴스를 찾지 못할 것입니다.

하지만 형의 회원들과 쉬운 솔루션이있다 : [A, T >: A]와 버전이 작동하지 않는 이유

trait AnyEnumerable { 

    type E 

    def name[A <: E](a: A): String 
    def list: List[E] 
} 

object Enumeration { 

    def name[A](a: A)(implicit ev: AnyEnumerable { type E >: A }) = ev.name(a) 
    def list[T](implicit ev: AnyEnumerable { type E = T }) = ev.list 
    // ... 
} 

// an implicit for `Season` 
implicit val seasonEnumerable: AnyEnumerable { type E = Season } = 
    new AnyEnumerable { 

    type E = Season 

    def name[A <: Season](a: A): String = a.toString 
    def list: List[Season] = List(Winter, Spring, Summer, Fall) 
    } 

// compiles! 
val zzz = Enumeration.name(Winter) 
관련 문제