2016-09-04 10 views
2

を入力情報とタイプクラスの実装を失う:それは持っていることの全体的なアイデアを中断しますので、caseを使用しない私は次のような関係を持っているScalaの

val xs: List[Foo] = ... 
xs.map(x => Doer(x)) // implicit not found since no implementation for type Foo. 

trait Bar[I <: Foo] { def doSomething(...) } 
object Doer { def apply[I <: Foo](...)(implicit ev: Bar[I]) = ev.doSomething(...) } 

trait Foo 

case class A(...) extends Foo 
object A { implicit object Something extends Bar[A] } 

case class B(...) extends Foo 
object B { implicit object SomethingElse extends Bar[B] } 

私は次のような状況を持っています将来の拡張性のための型クラス。

このような状況を処理するためには、何が必要ですか?

答えて

2

二つの主要な困難は

  1. 暗黙のは、コンパイラによって解決される問題で見ることができます。抽象型を持っているが具体的な意味を必要とする場所では、事前定義された型クラスインスタンスを結果コードに何とか持ちこたえなければなりません。
  2. サブタイプを抽象化することは、タイプライクな抽象化をひどく使います。これらを組み合わせるには多くの妥協点と回避策が必要です。

しかし、我々は我々は、おそらく解決暗黙の維持のためにいくつかのデータ型を作成することができ、この

trait Bar[+I] {def doSomething[J >: I](x: J): String} 
object Doer { 
    def apply[I <: Foo](el: I)(implicit ev: Bar[I]) = ev.doSomething(el) 
} 

trait Foo 

case class A() extends Foo 
object A { 
    implicit object Something extends Bar[A] { 
    def doSomething[X >: A](el: X) = "do A" 
} 
} 

case class B() extends Foo 
object B { 
    implicit object SomethingElse extends Bar[B] { 
    def doSomething[X >: B](el: X) = "do B" 
    } 
} 

のような定義を持っている想像してみましょう:今、あなたは

val xs: List[MemoTC[Foo, Bar]] = List(MemoTC(A()), MemoTC(B())) 
xs.map(x => x.withTC(x ⇒ implicit bar ⇒ Doer(x))) 
のような奇妙なコードを書くことができ

case class MemoTC[+Value, TC[+_]](value: Value)(implicit tc: TC[Value]) { 
    def withTC[Result](action: (Value) ⇒ TC[Value] ⇒ Result): Result = 
    action(value)(tc) 
} 

よろしくお願いしますこの例は、存在型の助けを借りて適合させることもできる:

trait Bar[I] {def doSomething(x: I): String} 
object Doer { 
    def apply[I <: Foo](el: I)(implicit ev: Bar[I]) = ev.doSomething(el) 
} 

trait Foo 

case class A() extends Foo 
object A { 
    implicit object Something extends Bar[A] { 
    def doSomething(el: A) = "do A" 
    } 
} 

case class B() extends Foo 
object B { 
    implicit object SomethingElse extends Bar[B] { 
    def doSomething(el: B) = "do B" 
    } 
} 

abstract class MemoTC[Abstract, TC[_]] { 
    type Concrete <: Abstract 
    val value: Concrete 
    val inst: TC[Concrete] 

    def withTC[Result](action: (Concrete) ⇒ TC[Concrete] ⇒ Result): Result = 
    action(value)(inst) 
} 

object MemoTC { 
    def apply[A, C <: A, TC[_]](v: C)(implicit tc: TC[C]) = new MemoTC[A, TC] { 
    type Concrete = C 
    val value = v 
    val inst = tc 
    } 
} 


val xs: List[MemoTC[Foo, Bar]] = List(MemoTC(A()), MemoTC(B())) 
xs.map(x => x.withTC(x ⇒ implicit bar ⇒ Doer(x))) 
関連する問題