Pattern matching for dependent types - how to avoid asInstanceOf?

I am drawing a space on how to accomplish the following without cheating and using asInstanceOf .

Let's say I have some kind of arbitrary private object type, each with its own type members.

  sealed trait Part { type A } case object P1 extends Part { override type A = String } case object P2 extends Part { override type A = Int } 

Now let's say that I connect P and the value of PA together ...

  trait PartAndA { val p: Part val a: pA } object PartAndA { type Aux[P <: Part] = PartAndA {val p: P} def apply(_p: Part)(_a: _p.A): Aux[_p.type] = new PartAndA { override val p: _p.type = _p override val a = _a } } 

How can I safely do the following with fatigue testing and without manual casting?

  def fold[A](pa: PartAndA)(p1: PartAndA.Aux[P1.type] => A, p2: PartAndA.Aux[P2.type] => A): A = pa.p match { case P1 => p1(pa.asInstanceOf[PartAndA.Aux[P1.type]]) case P2 => p2(pa.asInstanceOf[PartAndA.Aux[P2.type]]) } 
+5
source share
1 answer

I think your problem is with erasing jvm styles . Without this, your problem can be simplified:

 sealed trait Part { type A } case class P1() extends Part { override type A = String } case class P2() extends Part { override type A = Int } trait PartAndA[P <: Part] { val p: P val a: pA } object PartAndA { type Aux[P <: Part] = PartAndA[P] def apply(_p: Part)(_a: _p.A): PartAndA[_p.type] = new PartAndA[_p.type] { override val p: _p.type = _p override val a = _a } } def fold[A, T: ClassTag](pa: PartAndA[T])(p1: PartAndA[P1] => A, p2: PartAndA[P2] => A): A = pa match { case s: PartAndA[P1] => p1(pa) // here P1 is lost, err case i: PartAndA[P2] => p2(pa) // here P2 is lost, err } 

To my knowledge, there is no shorter (than yours or with typeTags / classTags ) jvm type erase bypass.

+1
source

All Articles