I am trying to implement the Stream transducer described in Functional Programming in Scala in chapter 15.
The authors do not use variance for the process type parameters Process[I, O]. However on the pursuit of really understanding variance, I added variance to the type parameters as such: Process[-I, +O].
All was well until I tried implementing the filter function and got the following compile error:
contravariant type I occurs in covariant position in type I => Boolean of value p
This is the setup code that I have been working with:
sealed trait Process[-I, +O] { self =>
import Process._
def apply(s: Stream[I]): Stream[O] = this match {
case Halt => Stream()
case Await(recv) =>
s match {
case h #:: t => recv(Some(h))(t)
case xs => recv(None)(xs)
}
case Emit(h, t) => h #:: t(s)
}
def filter(p: I => Boolean): Process[I, O] = self match {
case Halt => Halt
case Await(recv) =>
Await {
case Some(i) if (p(i)) => recv(Some(i))
case _ => recv(None)
}
case Emit(head, tail) => Emit(head, tail.filter(p))
}
}
object Process {
case class Emit[I, O](
head: O,
tail: Process[I, O] = Halt
) extends Process[I, O]
case class Await[I, O](
recv: Option[I] => Process[I, O]
) extends Process[I, O]
case object Halt extends Process[Any, Nothing]
}
I have already tried modifying filter signature to this:
def filter[II >: I](p: I => Boolean): Process[II, O]
Also tried changing Await to have the following type params:
case class Await[I, O, II >: I](
recv: Option[I] => Process[II, O]
) extends Process[I, O]
But still did not manage to compile this code.
Any ideas?