2016-11-28 19 views
3

スーパータイプAに対して暗黙的に定義されている場合、タイプBの暗黙のパラメータを解決できますか?ここスーパータイプから暗黙のパラメータを解決する

は一例であり:

Iが列挙型クラス有する:私は列挙のインスタンスを定義

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 

    // ... 
} 

を:

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(冬)が失敗する場合私は冬がシーズンだとスカラックに伝えません。私は '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 name [A](a:A)(暗黙のev:Enumerable [_>:A])= ev.name(a) とdef name [A、T> A](a:A)(暗黙のev:Enumerable [T])= ev.name(a)? – Loic

+1

私は答えを広げました。 –

3

タイプ依存型を推定する必要がある場合は、一般的に不便です。あなたの方法は

Winterで呼び出さ
def name[A, T >: A](a: A)(implicit ev: Enumerable[T]) 

、最初AWinter.typeに推測されますと、それはそのバウンドに準拠しており、その時点で、それには多くの制約があるとして、その後Tは、Aします。もちろん、コンパイラは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) 
関連する問題