I am trying to create an implementation of a trait that uses a match type, where the right-hand-side of that match type is known in advance. However, I can't seem to get the compiler to accept my "proof" of this. This is pretty new to me, so sorry if this is really obvious. Can someone help me understand if/how I can achieve what I want?
Here's some minimal code (Scastie) to illustrate what I'm doing:
class NumberBox {}
class LongBox {}
trait Boxer[T] {
def box(): Boxer.Box[T]
}
object Boxer {
type Box[T] = T match
case Long => LongBox
case _ => NumberBox
}
case class Val[T](v: T) extends Boxer[T] {
def box(): Boxer.Box[T] = v match
case _: Long => new LongBox()
case _ => new NumberBox()
}
// here we prove that Boxer.Box[T] is a NumberBox
case class NoLongs[T](v: Boxer[T])(using Boxer.Box[T] =:= NumberBox) extends Boxer[T] {
override def box(): Boxer.Box[T] = new NumberBox()
}
NoLongs(Val(1))
But this fails with:
Found: NumberBox
Required: Boxer.Box[T]
Note: a match type could not be fully reduced:
trying to reduce Boxer.Box[T]
failed since selector T
does not match case Long => LongBox
and cannot be shown to be disjoint from it either.
Therefore, reduction cannot advance to the remaining case
case _ => NumberBox
override def box(): Boxer.Box[T] = new NumberBox()