I have the following type class (similar to skunk.Twiddler):
/**
* A type class proving that `T` can be converted into an isomorphic Tuple of elements,
* each of which has `IsPrimtive[x]` instance or single-element Tuple if `x` is primtive already
*/
trait Dissect[T]:
type Out <: Tuple
def perform(t: T): Out
object Dissect:
type Aux[T, O] = Dissect[T] { type Out = O }
At some point later I need to combine:
Dissect[X] { type Out = (A, B) }- …and
Dissect[Y] { type Out = (C, D) } - …to get
Dissect[Z] { type Out = (A, B, C, D)}
But I cannot property extract Out from a given Dissect because type members are lost after summoning:
case class Foo(a: Int, b: String)
type T1 = Tuple.Map[(Int, Foo), Dissect]
// defined alias type T1
= (Dissect[Int], Dissect[Foo])
Now I want to convert T1 to (Int, (Int, String)):
type IsTuple[T <: Tuple] = T
type Extract[D] <: Tuple = D match
case Dissect.Aux[?, IsTuple[t]] => t
type T2 = Tuple.Map[T1, Extract]
// defined alias type T2
= (Extract[Dissect[Int]], Extract[Dissect[String]])
So the compiler cannot reduce Extract[Dissect[Int]] to Int *: EmptyTuple (althought there’s such instance).
How do I get Out?