map
メソッドを持つ型で機能する関数を実装しようとしていますflatMap
。私はすでに のためにそれを作っていますが、これにはandが直接Traversable
含まれていません。そこで、型クラスを使用して独自のインターフェイスを使用することにしました。Future
Option
trait CanMap[A, M[_]] {
def map[B](l: M[A])(f: A => B): M[B]
def flatMap[B](l: M[A])(f: A => M[B]): M[B]
}
私はすでにこれを実装しましたOption
:
implicit def canmapopt[A] = new CanMap[A, Option] {
def map[B](l: Option[A])(f: A => B): Option[B] = l.map(f)
def flatMap[B](l: Option[A])(f: A => Option[B]): Option[B] = l.flatMap(f)
}
これは非常にうまく機能します。の任意のサブタイプに対して実装したかったのでTraversable
、オプションの実装に非常に近い実装を試みました。
implicit def canmaptrav[A, B, T[B] <: Traversable[B]] = new CanMap[A, T] {
def map[B](l: T[A])(f: A => B): T[B] = l.map(f)
def flatMap[B](l: T[A])(f: A => T[B]): T[B] = l.flatMap(f)
}
しかし、私はエラーが発生します:
type mismatch; found : Traversable[B] required: T[B] Note: implicit method canmaptrav is not applicable here because it comes after the application point and it lacks an explicit result type
の戻り値の型l.map
。特定の type ではなくl.map(f)
a を返す理由がわかりません。だから私は明示的に適切なタイプの CanBuildFrom をコンテキストに入れようとしました:Traversable
T[B]
implicit def canmaptrav[A, B, T[B] <: Traversable[B]](implicit cbf: CanBuildFrom[T[A], B, T[B]]) = new CanMap[A, T] {
def map[B](l: T[A])(f: A => B): T[B] = l.map(f)
def flatMap[B](l: T[A])(f: A => T[B]): T[B] = l.flatMap(f)
}
エラーが続く。
私がどこで間違ったのか分かりますか?明らかかもしれませんが、私が推測するジェネリック型シグネチャと混同しています。
更新: 解決策
まず第一に、回答が指摘したように、CanMap
ほとんどが Functor/Monad であるため、勇気があれば、scalazを使用してこれを実装できます。ただし、あなたが私のようで、それなしで試してみたい場合は、Kipton Barros の回答に基づく解決策を次に示します。
trait CanMap[A, B, M[_]] {
def map(l: M[A])(f: A => B): M[B]
def flatMap(l: M[A])(f: A => M[B]): M[B]
}
implicit def canmapopt[A, B] = new CanMap[A, B, Option] {
def map(l: Option[A])(f: A => B): Option[B] = l.map(f)
def flatMap(l: Option[A])(f: A => Option[B]): Option[B] = l.flatMap(f)
}
implicit def canmaptrav[A, B, M[+_]](implicit bf: CanBuildFrom[M[A], B, M[B]], ev: M[A] => TraversableLike[A, M[A]], eb: M[B] => TraversableLike[B, M[B]]) = new CanMap[A, B, M] {
def map(l: M[A])(f: (A) => B): M[B] = l.map(f)
def flatMap(l: M[A])(f: A => M[B]): M[B] = l.flatMap[B, M[B]] { (a: A) =>
f(a)
}
}
秘訣は、M[A] => TraversableLike[A, M[A]]
サブタイプを試行する代わりに暗黙の変換を使用することTraversable
です。