If I have the following Scala type hierarchy:
// Base traits
trait TA[X <: TA[X,Y], Y <: TB[X,Y]]
trait TB[X <: TA[X,Y], Y <: TB[X,Y]]
trait TC[X <: TA[X,_]]
// More specific traits
trait TI[X <: TI[X,Y], Y <: TJ[X,Y]] extends TA[X,Y]
trait TJ[X <: TI[X,Y], Y <: TJ[X,Y]] extends TB[X,Y]
trait TK[X <: TI[X,_]] extends TC[X]
// Concrete class that should implement TK, but does not compile
class Z extends TK[TI[_,_]]
// What is needed to be able to get class Z to compile
// The reference of X to itself has been removed.
trait TC2[X <: TA[_,_]]
trait TK2[X <: TI[_,_]] extends TC2[X]
class Z2 extends TK2[TI[_,_]]
TC would be a generic manager of some sort of TA.
TK would be a more specific manager of a more specific TA (TI).
Z would be the concrete implementation that manages any object implementing TI.
Z is not legal, but Z2 is. Unfortunately, TC and TK are more specific than TC2 and TK2. So is there a way of declaring Z using TC and TK, instead of TC2 and TK2?
[EDIT] I failed to say in my original question, that I kind of understand why Z is unsound. What I really want to know is, if there is a way of saying something like:
class Z3 extends TK[TI[TI,_]]
When you have complex mutually recursive type bounds it can often be helpful see if you can translate your problem into an equivalent one using abstract type members instead. If we do that mechanically, your base and more specific traits end up looking like,
and now we have a straightforward definition of Z as,
Note that the definitions of the members of TA, TB and TI, TJ are essentially the same. Because these types are now type members we can factor them out into common base types like so,