enum EQ[A, B]:
case Refl[A]() extends (A `EQ` A)
object EQ:
given [A]: (A `EQ` A) = Refl()
import EQ.*
// Case 1
def f[A, B, C]: (A, A `EQ` B, B `EQ` C) => C =
case (a, Refl(), Refl()) => a // ok
def g[F[_], A, B]: (A, A `EQ` F[B]) => F[B] =
case (a, Refl()) => a // ok
def h[F[_], A, B, C]: (A, A `EQ` F[B], F[B] `EQ` F[C]) => F[C] =
case (a, Refl(), Refl()) => a // error
// Case 2
enum Nat:
case Z
case S[N <: Nat](n: N)
object Nat:
type Z = Z.type
enum Foo[A]:
case Bar extends Foo[Nat.Z]
def check[M <: Nat, N <: Nat](m: Foo[M], n: Foo[N]): Option[M `EQ` N] = (m, n) match
case (Foo.Bar, Foo.Bar) => Some(Refl()) // ok
def check[M <: Nat, N <: Nat](m: M, n: N): Option[M `EQ` N] = (m, n) match
case (Nat.Z, Nat.Z) => Some(Refl()) // error