GADT example fails to typecheck because it requires injectivity of type constructors
See original GitHub issueFound 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
Issue Analytics
- State:
- Created 5 years ago
- Comments:5 (5 by maintainers)
Top Results From Across the Web
Unsoundness due to GADT bounds ignoring type (un)injectivity
abgruszecki mentioned this issue on Dec 23, 2018. GADT example fails to typecheck because it requires injectivity of type constructors #4471.
Read more >Injective type families with GADTs - haskell - Stack Overflow
I tried a very simple example involving injective type families, but ... 'b' is a rigid type variable bound by a pattern with...
Read more >Injective type families (#6018) · Issues - GHC - GitLab
Add the constructor InjFamilyTyCon to TyConRhs and the family flavour InjectiveFamily to HsSyn . Again, I've opted to encode injectivity as a ...
Read more >Partial Type Constructors in Practice
For example : • The UArray type constructor describes arrays of unbox- able elements; type UArray Int (Int → Int) does not make...
Read more >Haskell/GADT - Wikibooks, open books for an open world
Generalised algebraic data-types (GADT) 75% developed ... a safe list type for which the equivalent of head [] fails to typecheck and thus...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@TomasMikula - thank you for the examples. I’ve added some very similar examples on #5611, taken from Haskell test suite.
The exact examples from this issue do typecheck, so I’m closing the issue. We still have #5658 to deal with.
You copied the old version with a mistake in the
Par
constructor:Also, your snippet mixes
Pair
andTuple2
(yourPar
constructor usesTuple2
, whereas the other ones usePair
).