I am using Rex Kerr's variant of Miles Sabin's idea for implementing unboxed union types in Scala. I have the following class:
class Foo[T] {
trait Contr[-A] {}
type Union[A,B] = {type Check[Z] = Contr[Contr[Z]] <:< Contr[Contr[A] with Contr[B]]}
def foo[U: Union[T,Foo[T]]#Check](x:U) = x match {
case _: Foo[T] => println("x is a Foo[T]")
case _: T @unchecked => println("x is a T")
}
}
This allows the following:
val aux = new Foo[Int]
aux.foo(aux) // prints "x is a Foo[T]"
aux.foo(42) // prints "x is a T"
aux.foo("bar") // does not compile
However:
val bar = new Foo[Foo[Int]]
bar.foo(bar) // OK: prints "x is a Foo[T]"
bar.foo(aux) // Not OK: prints "x is a Foo[T]"
Is there a way to fix this, and maybe also eliminate the @unchecked
?
EDIT
I think the Union
type, for this particular example, can be simplified to:
type Union[Z] = Contr[Contr[Z]] <:< Contr[Contr[T] with Contr[Foo[T]]]
and then the foo function can be:
def foo[U: Union](x:U) = ...
This makes the code simpler. However, the issue remains.