|
| 1 | +--- |
| 2 | +title: Scoped type variables only appears non-injectively in declaration header |
| 3 | +summary: A data declaration has a kind signature, where the implictly bound type variables cannot be matched up unambiguosly with the ones from the signature itself |
| 4 | +severity: error |
| 5 | +introduced: 9.6.4 |
| 6 | +--- |
| 7 | + |
| 8 | +The disconnected type variables error applies when kind-checking the header of a type/class declaration that has a |
| 9 | +separate, standalone kind signature. |
| 10 | + |
| 11 | +For this consider: |
| 12 | + |
| 13 | +```haskell |
| 14 | +type S a = Type |
| 15 | + |
| 16 | +type C :: forall k. S k -> Constraint |
| 17 | +class C (a :: S kk) where |
| 18 | + op :: .. kk .. |
| 19 | +``` |
| 20 | + |
| 21 | +Note that the class has a separate kind signature, so the elaborated decl should |
| 22 | +look like |
| 23 | + |
| 24 | +```haskell |
| 25 | +class C @kk (a :: S kk) where .. |
| 26 | +``` |
| 27 | + |
| 28 | +But how can we "connect up" the scoped variable `kk` with the skolem kind from the |
| 29 | +standalone kind signature for `C`? In general we do this by unifying the two. |
| 30 | +For example |
| 31 | + |
| 32 | +```haskell |
| 33 | +type T k = (k,Type) |
| 34 | +type W :: forall k. T k -> Type |
| 35 | +data W (a :: (x,Type)) = .. |
| 36 | +``` |
| 37 | + |
| 38 | +When we encounter `(a :: (x,Type))` we unify the kind `(x,Type)` with the kind `(T k)` |
| 39 | +from the standalone kind signature. Of course, unification looks through synonyms |
| 40 | +so we end up with the mapping `[x :-> k]` that connects the scoped type variable `x` |
| 41 | +with the kind from the signature. |
| 42 | + |
| 43 | +But in our earlier example this unification is ineffective, because `S` is a |
| 44 | +phantom synonym (and hence non-injective) that just discards its argument. So our answer to this issue is: |
| 45 | + |
| 46 | +> if matchUpSigWithDecl fails to connect `kk` with `k`, by unification, |
| 47 | +> we give up and complain about a "disconnected" type variable. |
| 48 | + |
| 49 | +The fix is easy: just add an explicit `@kk` parameter to the declaration, to bind `kk` |
| 50 | +explicitly, rather than binding it implicitly via unification. |
| 51 | + |
| 52 | +More discussion can be found [at ghc issue #24083](https://gitlab.haskell.org/ghc/ghc/-/issues/24083). |
| 53 | + |
| 54 | +This text was adapted from [Simon Peyton Jones' note on disconnected type variable, please refer to this note for more technical insight](https://gitlab.haskell.org/ghc/ghc/-/blob/2eee65e1a4f441e99b79f3dc6e7d60492e4cad78/compiler/GHC/Tc/Gen/HsType.hs#L3092-3147). |
0 commit comments