2

コンテキスト バウンドで、より高い種類の型の型コンストラクター パラメーターにアクセスすることは可能ですか? 高次の型を取り、コンストラクターパラメーターのインスタンスを返すメソッドを持つ特性を定義しようとしています。

case class A[TContents](c: TContents) {
  def foo = c
}

case class B[TContents](c: TContents) {
  def foo = c
}

trait Fooable[TClass[_ <: TContents], TContents] {
  def foo(obj: TClass[TContents]): TContents
}

case class AFooable[TContents] extends Fooable[A, TContents] {
  def foo(obj: A[TContents]) = obj.foo
}

case class BFooable[TContents] extends Fooable[B, TContents] {
  def foo(obj: B[TContents]) = obj.foo
}

class test {
  def getFoo[TType[_] : Fooable, TContents](obj: TType[TContents]): TContents = 
    implicitly[Fooable[TType, TContents]].foo(obj)

  implicit def aFooable = AFooable

  val a = A(1)
  val foo = getFoo(a)
}

これは、コンテキスト境界に 2 つの型パラメーターを含めることができないというコンパイラ エラーで失敗しますが、型コンストラクター パラメーターにアクセスする別の方法が見つかりませんか?

4

1 に答える 1

3

2 つのオプションがあります。タイプ ラムダ トリックを使用して部分的に適用しますFooable(うーん)。

def getFoo[TType[_]: ({type L[A[_]] = Fooable[A, TContents]})#L, TContents](
  obj: TType[TContents]
): TContents = implicitly[Fooable[TType, TContents]].foo(obj)

または、バインドされたコンテキストを脱糖します(私の意見では、はるかに優れています):

def getFoo[TType[_], TContents](obj: TType[TContents])(
  implicit ev: Fooable[TType, TContents]
): TContents = ev.foo(obj)

どちらの場合もaFooable、型パラメーターを指定する必要があることに注意してください。

implicit def aFooable[A] = AFooable[A]

また、パラメーター リストのないケース クラスに関する警告に従うことを強くお勧めします。

于 2012-12-06T14:01:04.200 に答える