Finally got this to work. Here's the infuriating code:

1 sealed trait Two[A,B] 2 case class One[A]() extends Two[A,A] 3 4 def convert[A,B](x: A, t: Two[A,B]): B = t match { 5 case One() => x 6 }

which of course gives:

type mismatch; found : x.type (with underlying type A) required: B case One() => x ^

You would think that Scala might introduce a constraint that `A =:= B`, but apparently not. Of course you could just make the `=:=` yourself

7 sealed trait Two[A,B] 8 case class One[A,B](pf: A =:= B) extends Two[A,B]

except that that is much more cluttered and not how people usually write and use case classes.

It turns out that the working solution is to use a matched (lower-case) type variable:

9 def convert[A,B](x: A, t: Two[A,B]): B = t match { 10 case o: One[a] => 11 x: a 12 }

So, the `match` is not as pretty as it could be, but the `case` class definition is clean and we never explicitly mentioned `=:=`, which is always a good thing.

(What's going on is that Scala is introducing two implicit `=:=` s, one linking `a` to `A` and one linking `a` to `B`, but doesn't chain implicits).

Thanks for posting this. I've been wondering about a solution to this for a while. Just a note: How would you use the `pf` variable on line 8 in a pattern match for the containing case class?

ReplyDelete