Обновление: Я изменил пример, чтобы его можно было скомпилировать и протестировать.Почему неявный класс Scala работает, когда одним из параметров типа должно быть Nothing?
У меня есть неявный класс, который определяет способ обогащения:
case class Pipe[-I,+O,+R](f: I => (O, R));
object Pipe {
// The problematic implicit class:
implicit class PipeEnrich[I,O,R](val pipe: Pipe[I,O,R]) extends AnyVal {
def >->[X](that: Pipe[O,X,R]): Pipe[I,X,R] = Pipe.fuse(pipe, that);
def <-<[X](that: Pipe[X,I,R]): Pipe[X,O,R] = Pipe.fuse(that, pipe);
}
def fuse[I,O,X,R](i: Pipe[I,O,R], o: Pipe[O,X,R]): Pipe[I,X,R] = null;
// Example that works:
val p1: Pipe[Int,Int,String] = Pipe((x: Int) => (x, ""));
val q1: Pipe[Int,Int,String] = p1 >-> p1;
// Example that does not, just because R = Nothing:
val p2: Pipe[Int,Int,Nothing] = Pipe((x: Int) => (x, throw new Exception));
val q2: Pipe[Int,Int,String] = p2 >-> p2;
}
Проблема заключается в том, что не работает, когда R
во втором примере Nothing
. Это приводит к ошибке компилятора: В таком случае, я получаю следующее сообщение об ошибке компилятора:
Pipe.scala:19: error: type mismatch; found : Pipe[Int,Int,R] required: Pipe[Int,Int,String] val q2: Pipe[Int,Int,String] = p2 >-> p2;
Почему это происходит?
мне удалось решить путем создания отдельного неявный класса для этого случая:
trait Fuse[I,O,R] extends Any {
def >->[X](that: Pipe[O,X,R])(implicit finalizer: Finalizer): Pipe[I,X,R];
}
protected trait FuseImpl[I,O,R] extends Any with Fuse[I,O,R] {
def pipe: Pipe[I,O,R];
def >->[X](that: Pipe[O,X,R]) = Pipe.fuse(pipe, that);
def <-<[X](that: Pipe[X,I,R]) = Pipe.fuse(that, pipe);
}
implicit class PipeEnrich[I,O,R](val pipe: Pipe[I,O,R])
extends AnyVal with FuseImpl[I,O,R];
implicit class PipeEnrichNothing[I,O](val pipe: Pipe[I,O,Nothing])
extends AnyVal with FuseImpl[I,O,Nothing];
Но я могу полагаться на поведение Scala в будущем, что он не будет рассматривать Nothing
в качестве опции для R
? Если это изменится в будущем, код перестанет работать, потому что у меня будет два разных применимых импликации.
Не должен 'Pipe.fuse (это, это)' быть скорее 'Pipe.fuse (pipe, that)'? – ghik
И, кстати, что такое 'B'? Кажется, он нигде не объявлен. – ghik
Не могли бы вы показать подпись 'Pipe.fuse'? – ghik