For my library i need to switch between two (not necessarily related) types. This can be done nicely with match types, like this
trait C { def show: Unit }
class XC extends C { def show = println("XC") }
class YC extends C { def show = println("YC") }
trait Top :
type Selector <: Boolean
type Z <: C
trait Worker[X <: XC,Y <: YC] extends Top :
type Z <: C = Selector match
case true => X
case false => Y
By defining the Selector
you can choose between X
or Y
. Implementations of Selector
can for instance be defined in a trait:
trait BaseTrait :
type Selector <: Boolean
trait FalseTrait extends BaseTrait :
type Selector = false
trait TrueTrait extends BaseTrait :
override type Selector = true
so you can use these as mixins to select. Like this:
class TestTrue() extends Worker[XC,YC], TrueTrait :
val z: Z = new XC
class TestFalse() extends Worker[XC,YC], FalseTrait :
val z: Z = new YC
In this Scastie you can see the whole lot in action.
This is al nice and good, but you are also obliged to use one of the traits, otherwise it will not compile, which is kind of understandable. But in my situation i want the “FalseTrait” trait to be the default, and give the user the ability to mixin the “TrueTrait”, so the type switches from Y
to X
, like this:
class TestBoth() extends Worker[XC,YC], FalseTrait, TrueTrait :
val z: Z = new XC
But this does not compile due to the type false
being incompatible to true
, see here. Is there a way to achieve this goal?