1

型クラスを定義する次のコードがあります。

trait Foo[T] {
  def toFoo(x: T): String
}

trait Foos {
  def toFoo[T](f: T => String): Foo[T] = new Foo[T] {
    def toFoo(x: T): String = f(x)
  }
}

object Foo extends Foos {
  def toFoo[A: Foo](a: A) = implicitly[Foo[A]].toFoo(a)
  implicit def AToFoo: Foo[A] = toFoo { c =>
    "A"
   }
  implicit def BToFoo[T]: Foo[B] = toFoo { c  => 
    "B"
  }

  implicit def ListToFoo[T: Foo]: Foo[List[T]] = toFoo { c =>
    c.map(toFoo(_)).
  }
}

class A
class B extends A

今、私が持っている場合、私はの代わりtoFoo(List(new A, new B)に取得します。タイプのクラスではなく、メソッドが使用されていることを確認するにはどうすればよいですか?List("A", "A")List("A", "B")BtoFooAToFooB

4

1 に答える 1

2

暗黙的な解決は、純粋にコンパイル時のメカニズムです。ここでサブタイプを区別する簡単な方法は、暗黙の内部で一致させることです。BToFoo完全に削除し、代わりにAバージョンで両方のケースを処理します

implicit val AIsFoo : Foo[A] = toFoo { 
  case b: B => "B"
  case a: A => "A"
}

もちろん、階層の一部のメソッドに委任することもできます。のメソッドに委任し、AでオーバーライドしBても、メソッドを追加できないListの型クラスを機能させることができます。

共変性を宣言することも検討してFooください。

于 2012-03-20T11:28:36.760 に答える