[GHC] #16146: Trivial partial type signature kills type inference in the presence of GADTs

GHC ghc-devs at haskell.org
Tue Jan 8 19:28:39 UTC 2019


#16146: Trivial partial type signature kills type inference in the presence of
GADTs
-------------------------------------+-------------------------------------
        Reporter:  goldfire          |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.6.3
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by goldfire):

 Why does quantification enter into it, now that I think of it?

 Let's look at some typing rules, where `<=` denotes checking and `=>`
 denotes inference in the bidirectional type system. I use `t` to denote a
 type (no wildcards) and `p` to denote a partial type (zero or more
 wildcards).

 {{{
 e <= t
 ------------ Sig
 (e : t) => t

 e => t1
 t1 <: t2
 -------- Infer
 e <= t2
 }}}

 These rules govern what happens when an expression with a complete type
 signature `(e : t1)` is checked against a type `t2`. Because there is no
 `<=` rule for the `(e : t1)` form, we use the Infer rule to switch into
 synthesis mode. Since we have `t1` as the type signature, we synthesize
 type `t1` for `(e : t1)`. Then, we check to make sure that `t1` is a
 subtype of `t2`. (Reminder: `t1` is a subtype of `t2` iff there is a
 computationally free way to convert a value of type `t1` to a value of
 type `t2`. Example: `forall a. a -> a` is a subtype of `Int -> Int`
 because we can instantiate a value of type `forall a. a -> a` with `Int`
 with no runtime cost.)

 Currently, this is the rule for an expression with a partial type
 signature:

 {{{
 e <~~ p => t
 ------------ PartialSig
 (e : p) => t
 }}}

 where `e <~~ p => t` means that checking `e` against partial signature `p`
 results in a type `t`. This is done by GHC's `simplifyInfer`.

 I propose adding a new rule to the system:

 {{{
 p <: t2 => p2
 e <~~ p2 => t
 t <: t2
 ------------- PartialSigCheck
 (e : p) <= t2
 }}}

 where `p <: t2 => p2` means:
 1. Check whether `p` is a subtype of `t2`.
 2. During this check, we might have to choose values for wildcards in `p`.
 3. `p2` is `p`, but with the wildcards zonked to have the values
 discovered in the subtype check.

 Note that `p2` might actually have no wildcards left. Regardless, we will
 use the `e <~~ p2 => t` (`simplifyInfer`) operation, as checking against a
 partial type signature is really quite different than checking against a
 complete type signature, and we wouldn't want unifications with the
 pushed-down type to chane this. Naturally, we have to do another subtype
 check, just to make sure that the type after `simplifyInfer` is suitable.
 (It's possible that we can prove that if `p <: t2 => p2` and `e <~~ p2 =>
 t`, then `t <: t2`. Indeed, that would be desirable. But I'm not sure
 right now if this would be true.)

 I ''think'' that would solve our problem. And it seems to make GHC
 strictly more expressive. And it would seem to be "what the user would
 expect", making use of information manifestly available (but, today,
 ignored).

 This would require writing a new subtyping check `p <: t2 => p2`. The
 implementation of subtyping in GHC is somewhat laborious, but it's not a
 particularly complicated judgment. It's unclear how much code-sharing this
 new form would have with the existing one, given the different way that
 partial types are represented internally.

 I agree that this is a GHC proposal. However, the consequences of this are
 subtle and hard to predict, so I want to have some debate here before
 going there.

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


More information about the ghc-tickets mailing list