Closed
Description
Found on Twitter, noting it here: https://gist.github.com/TomasMikula/ecdbde18f142ffda0a02219f0118d7ba
@TomasMikula correctly points out:
Note that for the typechecker to succeed, it will have to make use of the fact that Tuple2 is an injective type constructor, i.e. be able to derive A = C from (A, B) = (C, D).
Investigation status: Still poking at this, and even if I modify everything to avoid covariant ADTs from the stdlib (for simplicity) and make case classes final, the typechecker still seems to have problems with injectivity. Still need to fire up the debugger to see what happens inside.
case class Pair[A, B](a: A, b: B)
enum Maybe[A] {
case None()
case Just(a: A)
}
object WithInvTuple {
// Shorter notation for it
type ~[A, B] = Pair[A, B]
sealed trait Shuffle[A1, A2] {
def andThen[A3](that: Shuffle[A2, A3]) = Shuffle.AndThen(this, that)
}
object Shuffle {
final case class Id[A]() extends Shuffle[A, A]
final case class Swap[A, B]() extends Shuffle[A ~ B, B ~ A]
final case class AssocLR[A, B, C]() extends Shuffle[(A ~ B) ~ C, A ~ (B ~ C)]
final case class AssocRL[A, B, C]() extends Shuffle[A ~ (B ~ C), (A ~ B) ~ C]
final case class Par[A1, B1, A2, B2](_1: Shuffle[A1, A2], _2: Shuffle[B1, B2]) extends Shuffle[(A1, A2), (B1, B2)]
final case class AndThen[A1, A2, A3](_1: Shuffle[A1, A2], _2: Shuffle[A2, A3]) extends Shuffle[A1, A3]
def rewrite3[A1, A2, A3, A4](
op1: Shuffle[A1, A2],
op2: Shuffle[A2, A3],
op3: Shuffle[A3, A4]
): Maybe[Shuffle[A1, A4]] = (op1, op2, op3) match {
// case (Swap(), _, _) =>
// Maybe.Just(
// AssocLR[A1, A2 ~ A3, A4]()
// )
// case (_: Swap[a11 ~ a12, _]) =>
// Maybe.Just(
// // ???
// AssocLR[a11 ~ a12, A2 ~ A3, A4]()
// )
case (Swap(), AssocRL(), _) => Some(AssocLR[A1, A2 ~ A3, A4]())
//case (Swap(), AssocRL(), Par(Swap(), Id())) =>
//Some(AssocLR() andThen Par(Pair(Id(), Swap())) andThen AssocRL())
case _ =>
Maybe.None()
}
}
}
//output:
[info] Compiling 2 Scala sources to /Users/pgiarrusso/git/dotty-example-project/target/scala-0.8/classes ...
[error] -- [E007] Type Mismatch Error: /Users/pgiarrusso/git/dotty-example-project/src/main/scala/playground/mikulaGADT.scala:65:41
[error] 65 | case (Swap(), AssocRL(), _) => Some(AssocLR[A1, A2 ~ A3, A4]())
[error] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error] |found: Some[mikulaGADT.WithInvTuple.Shuffle.AssocLR[A1, mikulaGADT.Pair[A2, A3], A4]]
[error] |required: mikulaGADT.Maybe[mikulaGADT.WithInvTuple.Shuffle'[A1, A4]]
[error] |
[error] |where: A1 is a type in method rewrite3 which is an alias of mikulaGADT.Pair[A$1, B$1]
[error] | A2 is a type in method rewrite3 with bounds >: mikulaGADT.Pair[B$1, A$1] and <: mikulaGADT.Pair[B$1, A$1] & mikulaGADT.Pair[B$1, mikulaGADT.Pair[B$2, C$1]]
[error] | A3 is a type in method rewrite3 which is an alias of mikulaGADT.Pair[mikulaGADT.Pair[B$1, B$2], C$1]
[error] | Shuffle is a object in object WithInvTuple
[error] | Shuffle' is a trait in object WithInvTuple
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 2 s, completed May 6, 2018 2:56:44 PM