Pet*_*lák 1 monads scala covariance contravariance for-comprehension
假设我们有一个具有协变和逆变类型参数的类:
sealed trait Pipe[-I,+O,+R]
// case subclasses
Run Code Online (Sandbox Code Playgroud)
我们为此类的实例定义了单子操作:
object Pipe {
def flatMap[I,O,Ri,R](p: Pipe[I,O,Ri], f: Ri => Pipe[I,O,R]): Pipe[I,O,R] =
...
}
Run Code Online (Sandbox Code Playgroud)
为了能够使用for-理解,我们需要它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);
}
Run Code Online (Sandbox Code Playgroud)
但是,这不会编译,失败并显示
逆变类型
I出现在(R) => Pipe[I,O,R1]value类型的协变位置f。
(协变类型参数也会出现类似的错误。)
我了解该限制以及出现问题的原因。但是是否有一些解决方法,如何使用与上面相同的语义flatMap来定义特征?Pipes.flatMap也许使用一些隐式转换和/或中间构建器类?
最简单的是,
\n\nimplicit def pipeFlatMap[I, O, A](pipe: Pipe[I, O, A]) = new {\n def flatMap[B](f: A => Pipe[I, O, B]) = Pipe.flatMap(pipe, f)\n}\nRun Code Online (Sandbox Code Playgroud)\n\n如果您Pipe允许实现point, ie def point[I, O, A](a: A): Pipe[I, O, A],那么实现完整的scalaz.Monad类型类可能会很有用,因为 Scalaz 的隐式将为您flatMap免费提供许多其他一元操作:
implicit def pipeMonad[I, O] = new Monad[({type \xce\xbb[\xce\xb1]=Pipe[I, O, \xce\xb1]})#\xce\xbb] {\n // TODO implement point and bind\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
293 次 |
| 最近记录: |