[GHC] #16148: Better type inference for Constraint vs Type

GHC ghc-devs at haskell.org
Tue Jan 8 10:56:01 UTC 2019


#16148: Better type inference for Constraint vs Type
-------------------------------------+-------------------------------------
           Reporter:  simonpj        |             Owner:  (none)
               Type:  bug            |            Status:  new
           Priority:  normal         |         Milestone:
          Component:  Compiler       |           Version:  8.6.3
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  None/Unknown
  Unknown/Multiple                   |
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 An enduring infelicity in GHC’s type inference is the treatment of tuples.
 Consider, this from `RaeJobTalk`:
 {{{
 type family F c sch where
   F _ '[] = (() :: Constraint)
   F c (col ': cols) = (c Int, F c cols)
 }}}
 When kind-checking `F`, we initially give it a return kind of kappa, a
 unification variable.  Suppose we kind-check the second equation first.
 Then what kind of tuple is it, a constraint tuple, or an ordinary type
 tuple.  We must unify kappa with `Type` or `Constraint` respectively – and
 they are different kinds.  How can we choose which?
 Currently we have the following unsatisfactory ruse:

 1. Look at the “expected kind”.   If we kind-check the second equation
 first we learn nothing from that
 2. Infer kinds for all of the elements of the type.  Again in this case we
 learn nothing.
 3. If we still know nothing, arbitrarily pick Type

 This is horrible.  If we kind check the first equation first, step 1 will
 discover Constraint, and kind checking succeeds.  But if we put the
 equations in the other order, kind checking fails.  Ugh!

 Another example with exactly the same cause is #16139.

 What to do?  I can only think of three approaches:

 A. Add a pseudo constraint `(TC kappa)` meaning “kappa must eventually
 turn out to be either `Type` or `Constraint`”.   When generalising,
 default to `Type`.

 B. Same, but by having a special sort of TauTv, a TCTv, which can only
 unify with Type or Constraint.  Again, do not generalise over such type
 variables.

 C. Define
 {{{
 type Type = TYPE (LiftedRep T)
 type Constraint = TYPE (LiftedRep C)
 }}}
     So now we can unify `kappa` with `(TYPE (LiftedRep zeta))` where
 `zeta` is a unification variable that we must eventually unify with `T` or
 `C`.

 Of these, (C) seems most principled, but somehow over-elaborate for our
 purposes.   And the others also seem to be rather too much work to solve a
 simple, local problem.

 -------------
 For reference, here are the current kinding rules
 {{{
           t1 : TYPE rep1
           t2 : TYPE rep2
     (FUN) ----------------
           t1 -> t2 : Type

           t1 : Constraint
           t2 : TYPE rep
   (PRED1) ----------------
           t1 => t2 : Type

           t1 : Constraint
           t2 : Constraint
   (PRED2) ---------------------
           t1 => t2 : Constraint

           ty : TYPE rep
           `a` is not free in rep
 (FORALL1) -----------------------
           forall a. ty : TYPE rep

           ty : Constraint
 (FORALL2) -------------------------
           forall a. ty : Constraint
 }}}

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


More information about the ghc-tickets mailing list