I have the following idea:
trait Generator[A] {
def generate: Stream[A]
// (1) If A <: Int
def +(other: Generator[Int]): Generator[Int] = (
CustomGeneratorInt(
(this.asInstanceOf[Generator[Int]].generate, other.generate)
.zipped
.map(_ + _))
)
// (2) If A <: Boolean
def &&(other: Generator[Boolean]): Generator[Boolean] = ...
}
case class CustomGeneratorInt(val generate: Stream[Int]) extends Generator[Int]
case class ConstantInt(i: Int) extends Generator[Int] { def generate = Stream(i) }
case class ConstantBool(i: Boolean) extends Generator[Boolean] { def generate = Stream(i) }
case class GeneratorRandomInt(i: Int) extends Generator[Int] { def generate = ... }
ConstantInt(1) + ConstantInt(2) // (3) ok
ConstantBool(true) && ConstantBool(false) // (4) ok
ConstantInt(1) + ConstantBool(false) // (5)
ConstantBool(true) + ConstantInt(1) // (6) compiles but it's bad
ConstantBool(true) && ConstantInt(1) // (7)
ConstantInt(1) && ConstantBool(true) // (8) compiles but it's bad
I would like (1) and (2) to raise a compiler exception if they are not applied in a right scheme. For example, although (6) and (8) currently compiles, they should not. (5) and (7) already do not compile. How to specify this type condition to which to apply those methods?