[GHC] #13761: Can't create poly-kinded GADT with TypeInType enabled, but can without

GHC ghc-devs at haskell.org
Fri Jun 2 00:24:06 UTC 2017


#13761: Can't create poly-kinded GADT with TypeInType enabled, but can without
-------------------------------------+-------------------------------------
        Reporter:  RyanGlScott       |                Owner:  (none)
            Type:  bug               |               Status:  closed
        Priority:  normal            |            Milestone:
       Component:  Compiler (Type    |              Version:  8.0.1
  checker)                           |
      Resolution:  invalid           |             Keywords:  TypeInType
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  GHC rejects       |  Unknown/Multiple
  valid program                      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by goldfire):

 A separate kind signature will be understood independent of the type
 definition -- much like how type signatures on functions are understood
 (and kind-generalized) independently of the body.

 For example, consider

 {{{
 data Proxy (a :: k) = P
 data S :: Proxy k -> Type where
   MkS :: S (P :: Proxy Maybe)
 }}}

 What's the type of `k`? Taking the definition into account, we can see
 that `k :: Type -> Type`. But if we must take the definition into account,
 then we don't have a CUSK, by definition. Currently, the declaration above
 causes GHC to complain that `Type -> Type` does not match `k`, as we're
 using `S` at a different instantiation in its body than in its head (i.e.
 using polymorphic recursion). Change to

 {{{
 data S :: forall k. Proxy k -> Type where ...
 }}}

 and now we get

 {{{
     You have written a *complete user-suppled kind signature*,
     but the following variable is undetermined: k0 :: *
     Perhaps add a kind signature.
 }}}

 This is quite correct. The declaration looks like it has a CUSK, but
 really it doesn't.

 Instead, we can write

 {{{
 data S :: forall (k :: Type -> Type). Proxy k -> Type where ...
 }}}

 or

 {{{
 data S :: forall (kk :: Type) (k :: kk). Proxy k -> Type where ...
 }}}

 both of which are accepted. Note that these define ''different'' types:
 the second defines a kind-indexed GADT.

 The point of all this is that it's incredibly confusing. Much better would
 be

  (*) A definition can use polymorphic recursion if it has a standalone
 type/kind signature.

 Simple! It works for types and terms. And it's exactly what happens for
 terms today.

 Under (*), all the declarations for `S` would be rejected, as none of them
 have a standalone kind signature. (The proposal will also describe
 `-XCUSKs`, on by default, that retains the current behavior. This
 extension will be off by default and deprecated in due course.)

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13761#comment:7>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list