I recently had an interesting scala riddle that includes existential types and type aliases ( https://softwaremill.com/scala-riddle ), and I realized that when the type alias does not work, we should try the restricted members of the abstract type.
I did not understand any template that could tell me which type of type member I need to apply in a particular situation. I can not find the answer in the documentation, maybe this is an implementation detail?
I hope there is someone who can help me find such a template or at least give some new tips.
How I worked with your code
Inside PairT I replaced type aliases ( type T1 = A ) with strictly restricted abstract types ( type T1 >: A <: A ) and .. it works (scalac 2.11.4).
What's even more interesting is that PairC , which is a concrete class, will only work with type aliases - if I try to replace them with restricted members of an abstract type, it will cause a compilation error.
Below is all the code after my modifications:
package so1 import scala.language.existentials object SOPuzzle { type PairT[F, S] = { type T1 >: F <: F type T2 >: S <: S } class PairC[F, S] { type T1 = F type T2 = S } case class TMap[T, U](a: T, b: U) { def consumeA(a: T): T = a def consumeB(b: U): U = b } type MapC2[A] = TMap[p.T1, p.T2] forSome {val p: PairC[A, A]} type MapC2V2[A] = TMap[PairC[A, A]#T1, PairC[A,A]#T2] type MapT2[A] = TMap[p.T1, p.T2] forSome {val p: PairT[A, A]} type MapT2V2[A] = TMap[PairT[A, A]#T1, PairT[A, A]#T2] val c2: MapC2[Int] = TMap(1, 2) val c2v2: MapC2V2[Int] = TMap(1, 2) val t2: MapT2[Int] = TMap(1, 2) val t2v2: MapT2V2[Int] = TMap(1, 2) val i1:Int = c2.consumeA(0) val i2:Int = c2.consumeB(0) val i3:Int = c2v2.consumeA(0) val i4:Int = c2v2.consumeB(0) val i5:Int = t2.consumeA(0) val i6:Int = t2.consumeB(0) val i7:Int = t2v2.consumeA(0) val i8:Int = t2v2.consumeB(0) }