1

共変と反変の型パラメーターを持つクラスがあるとします。

sealed trait Pipe[-I,+O,+R]
// case subclasses

そして、このクラスのインスタンスに対して定義されたモナド操作があります。

object Pipe {
    def flatMap[I,O,Ri,R](p: Pipe[I,O,Ri], f: Ri => Pipe[I,O,R]): Pipe[I,O,R] =
        ...
}

for-comprehensionを使用できるようにするにflatMapは、それがトレイト自体のメソッドである必要があります。

sealed trait Pipe[-I,+O,+R] {
    def flatMap[I,O,Ri,R](f: Ri => Pipe[I,O,R]): Pipe[I,O,R] =
        Pipe.flatMap(this, f);
}

ただし、これはコンパイルされず、失敗します

反変型は、値のI型の共変位置にあります。(R) => Pipe[I,O,R1]f

(共変型パラメータでも同様のエラーが発生します。)

制限と問題が発生する理由を理解しています。しかし、上記と同じセマンティクスflatMapを使用して特性を定義する方法はありますか? Pipes.flatMapおそらく、いくつかの暗黙的な変換や中間ビルダー クラスを使用していますか?

4

1 に答える 1

5

最も簡単に言えば、

implicit def pipeFlatMap[I, O, A](pipe: Pipe[I, O, A]) = new {
  def flatMap[B](f: A => Pipe[I, O, B]) = Pipe.flatMap(pipe, f)
}

Scalazの暗黙の実装により、他の多くのモナディック操作が無料で提供されるため、Pipe実装が許可されている場合point、つまりdef point[I, O, A](a: A): Pipe[I, O, A]、完全な型クラスの実装が役立つ場合があります。scalaz.MonadflatMap

implicit def pipeMonad[I, O] = new Monad[({type λ[α]=Pipe[I, O, α]})#λ] {
  // TODO implement point and bind
}
于 2013-03-03T10:28:24.543 に答える