Допустим, у нас есть класс с ковариантным и контравариантным параметрами типа:
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
-computing, нам нужно, чтобы 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
с той же семантикой, что и выше? Возможно, с использованием некоторых неявных преобразований и / или промежуточного класса построителя?