[GHC] #9858: Typeable instances should be kind-aware

GHC ghc-devs at haskell.org
Wed Apr 15 00:56:27 UTC 2015


#9858: Typeable instances should be kind-aware
-------------------------------------+-------------------------------------
        Reporter:  dreixel           |                   Owner:
            Type:  bug               |                  Status:  merge
        Priority:  highest           |               Milestone:  7.10.2
       Component:  Compiler          |                 Version:  7.9
      Resolution:                    |                Keywords:
Operating System:  Unknown/Multiple  |            Architecture:
 Type of failure:  None/Unknown      |  Unknown/Multiple
      Blocked By:                    |               Test Case:
 Related Tickets:                    |  typecheck/should_fail/T9858a,
                                     |  should_run/T9858b
                                     |                Blocking:
                                     |  Differential Revisions:  Phab:D652
-------------------------------------+-------------------------------------

Comment (by ekmett):

 Rather than just say it is sad, let's see if we can tackle this issue head
 on.

 A while back, Simon, you posed a sketch of an idea of how to remove the
 superkinding / existing type hacks by adding another very simple level we
 can quantify over.

 It could be adapted to address this situation.

 Consider a type checker where we've removed `*`, `Constraint` and `#` and
 made a single unified kind `Sort a b` where `a` and `b` are allowed to
 range over a binary alphabet, lets consider `{T,F}` as that alphabet. [*]

 Then

 {{{
 * = Sort T T
 Constraint = Sort T F
 # = Sort F T
 }}}

 and we can talk about the kinds of existing types:

 {{{
 () :: forall a. Sort T a
 }}}

 lets `()` work as both a `Constraint` or `*`.

 {{{
 (,) :: forall a. Sort T a -> Sort T a -> Sort T a
 }}}

 lets us tuple up anything as long as both are *'s or both are Constraints.

 Unboxed tuples fit:

 {{{
 (#,#) :: forall a b. Sort a T -> Sort a T -> Sort F T
 }}}

 lets unboxed tuples carry `*`'s and `#`'s.

 and the existing function overloads fit:

 {{{
 (->) :: forall a b. Sort a T -> Sort b T -> Sort T T
 }}}

 All of this then works without the typechecker ever internally lying to
 itself which then solves this issue in a principled way, as the Typeable
 instance can know the full choice of kind without subversion.

 This removes all of the hacks where `(->) :: * -> * -> *`   but `a -> b`
 might have `a` and `b` have kinds other than `*`, etc. in the typechecker,
 and lets us talk about `(->) Int#`, or `(,) (Eq Int)` which are both types
 we currently can't write:

 {{{
 ghci> :k (->) Int#

 <interactive>:1:6:
     Expecting a lifted type, but ‘Int#’ is unlifted
     In a type in a GHCi command: (->) Int#
 }}}

 I already have to work around the lack of the latter by constructing my
 own product for constraints.

 {{{
 class (p,q) => p & q
 instance (p,q) => p & q
 }}}

 Now I can talk about `(&) (Eq Int) :: Constraint -> Constraint`, but there
 is no corresponding partial application trick for `(->)`.

 We've already implemented a related trick in Ermine without appreciable
 impact, our kinds there are a little different, so the details vary a bit.

 [*] To prevent weird quantifier abuse, you may want to require each of the
 arguments of Sort to have different ranges, otherwise `Sort a a` becomes
 weird.

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


More information about the ghc-tickets mailing list