[GHC] #15674: GADT's displayed type is misleading

GHC ghc-devs at haskell.org
Sat Sep 29 21:05:16 UTC 2018


#15674: GADT's displayed type is misleading
-------------------------------------+-------------------------------------
        Reporter:  AntC              |                Owner:  (none)
            Type:  feature request   |               Status:  new
        Priority:  normal            |            Milestone:  8.6.1
       Component:  Compiler          |              Version:  8.6.1-beta1
      Resolution:                    |             Keywords:
Operating System:  Windows           |         Architecture:  x86_64
 Type of failure:  Poor/confusing    |  (amd64)
  error message                      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by goldfire):

 Replying to [comment:5 AntC]:
 > > There is no `forall` in `MkDG`, which doesn't quantify over any
 variables.
 > >
 >
 > Then I totally ignore the `a` in the `data DG a where ...`?

 In GADT syntax, the bit between the `data` and the `where` is the
 declaration for the type only -- not any constructors. The `a` there
 serves to say that `DG` takes one argument. It does not affect or cause
 any variable quantification in constructors.

 >
 > For `MkDG2`, with `-fprint-explicit-foralls`
 >   `:i` shows `MkDG2 :: forall a. (a ~ Int) => a -> DG a`
 >
 >   `:t` shows `MkDG2 ::                      Int -> DG Int`
 >
 > With `-fno-print-explicit-foralls`
 >   `:i` shows `MkDG2 ::           (a ~ Int) => a -> DG a`
 >
 >   `:t` shows `MkDG2 ::                      Int -> DG Int`
 >
 > Is that intended behaviour? It doesn't seem either internally
 consistent, nor consistent with your explanation: why is the `forall`
 appearing at all? Why is it appearing for `:i` but not `:t`?

 Yes, this is all expected behavior. Haskell allows you omit `forall`s if
 you have a type variable in a type. But when you write `-fprint-explicit-
 foralls`, it will print one even if you left it out. So: the `forall`
 appears because you asked for it.

 I'll quote myself:

 > `:type <expr>` gives you the type that is assigned to it if you had `let
 it = <expr>`. It's a uniform rule that always works.

 When we say `let it = MkDG2`, GHC instantiates the type of `MkDG2` at its
 occurrence and then generalizes (because `let`-bound variables are
 generalized). Thus, `it` might not have exactly the same type as `MkDG2`,
 which is what's happening here.

 Here's a simpler example:

 {{{#!hs
 silly :: (Ord a, Eq a) => a -> Bool
 silly = ...
 }}}

 Asking for `:t silly` gives you `Ord a => a -> Bool`. This is because we
 instantiate and regeneralize the type of `silly`. In this process, GHC
 realizes that `Eq a` is redundant and drops it. The same is happening with
 `MkDG2`.


 > What I'm looking for with these mind-blowingly similar-but- "subtly
 different" nuances is strong help from the compiler to navigate error
 messages when I get my types wrong.

 Short of a use of a type application (which doesn't seem to be what you're
 doing), `MkDG` and `MkDG2` behave identically.

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


More information about the ghc-tickets mailing list