How to best display type variables with the same name

Simon Peyton Jones simonpj at microsoft.com
Wed Oct 26 10:43:22 UTC 2016


Chris

As far as I understand it:

·         You are plucking a type from the midst of a syntax tree, and displaying it.

·         That type might well mention type variables that are bound “further out”

o   either by a forall (if this is a sub-tree of a type)

o   or by a big lambda

·         There are some tricky UI issues in how to display such types to the user.

Generally, I think it’s mainly up to you to track which type variables are in scope from “further out”.  It’s not a property that is stable under transformation, so it’s not part of the TyVar.

The typechecker itself uses “tidying” to avoid accidentally displaying distinct type variables in the same way.  See TyCoRep.tidyType and related functions.  They may be useful to you too.

Hard for me to say more… I’m swamped, and there are genuine UI issues here.  Maybe some folk on Haskell Café might be interested.

Simon

From: Christopher Done [mailto:chrisdone at gmail.com]
Sent: 21 October 2016 15:07
To: Simon Peyton Jones <simonpj at microsoft.com>
Cc: ghc-devs at haskell.org
Subject: Re: How to best display type variables with the same name


On 19 October 2016 at 17:00, Simon Peyton Jones simonpj at microsoft.com<https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmailto%3Asimonpj%40microsoft.com&data=02%7C01%7Csimonpj%40microsoft.com%7C4c125c4fe1834a3a959708d3f9bb9d1b%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636126556597550377&sdata=hGnspUNnWUxTUXA%2FS%2F%2B7mw6J2WyqirrsacU21TGRk0U%3D&reserved=0> wrote:

I’m afraid I didn’t understand the issue in the link below. It
speaks of “querying the type”, but I’m not sure what that means. A
GHCi session perhaps? Does this relate to the way GHCi displays
types?

I’m a bit lost. A from-the-beginning example, showing steps and
what the unexpected behaviour is would be helpful (to me anyway)

Sure. I’ll explain from top-level down:

·         In this case “querying the type” means running the :type-at
command in Intero (which itself is a fork of GHCi’s codebase around
GHC 7.10):
https://github.com/commercialhaskell/intero/blob/master/src/InteractiveUI.hs#L1693-L1713<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fcommercialhaskell%2Fintero%2Fblob%2Fmaster%2Fsrc%2FInteractiveUI.hs%23L1693-L1713&data=02%7C01%7Csimonpj%40microsoft.com%7C4c125c4fe1834a3a959708d3f9bb9d1b%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636126556597550377&sdata=C9rd1twSgpzdJ9UbdUZL4h8oCMBUrXJKGYjSlaoqrqc%3D&reserved=0>
It accepts a file name, line-col to line-col span and prints the
type of that expression/pattern. As you can see in that function it
uses printForUserModInfo (from GhcMonad), similar to (scroll above)
the printForUser for GHCi’s regular :type command.

·         Where does that info come from? When we load a module in Intero, we
perform an additional step of “collecting info” here:
https://github.com/commercialhaskell/intero/blob/master/src/GhciInfo.hs#L73<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fcommercialhaskell%2Fintero%2Fblob%2Fmaster%2Fsrc%2FGhciInfo.hs%23L73&data=02%7C01%7Csimonpj%40microsoft.com%7C4c125c4fe1834a3a959708d3f9bb9d1b%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636126556597550377&sdata=lI4KU9JbM3tb7ZrEp684eHi1EixchPn1aeOXsUab6sU%3D&reserved=0>
That info, for each node in the AST, is ultimately stored in a
SpanInfo:
https://github.com/commercialhaskell/intero/blob/master/src/GhciTypes.hs#L28-L39<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fcommercialhaskell%2Fintero%2Fblob%2Fmaster%2Fsrc%2FGhciTypes.hs%23L28-L39&data=02%7C01%7Csimonpj%40microsoft.com%7C4c125c4fe1834a3a959708d3f9bb9d1b%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636126556597550377&sdata=MLkyE0K2jJL%2FOE%2BnMMl1IuJ633u2jTL16BIz%2F0lK%2FEo%3D&reserved=0>
Which we then use for :type-at.

So in summary we collect info from tm_typechecked_source, keep that
for later, and then when the user’s editor asks via e.g. :type-at X.hs 1 5 1 7 “what is the type of the thing at this point?” we use
GHC’s regular pretty printing function to print that type.

That actually all works splendidly. For example, if we query

foo g f = maybe g f

--  ^ here or   ^ here yields g :: b

foo g f = maybe g f

--    ^ here or   ^ here yields: f :: a -> b

The tricky part arises in this example:
https://github.com/commercialhaskell/intero/issues/280#issuecomment-254784904<https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fcommercialhaskell%2Fintero%2Fissues%2F280%23issuecomment-254784904&data=02%7C01%7Csimonpj%40microsoft.com%7C4c125c4fe1834a3a959708d3f9bb9d1b%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636126556597550377&sdata=r6WMD%2BUl6ilAyDX4V%2FibPSQqM9UPlBPrOUCMjjmHj9c%3D&reserved=0>

Which is that we have two perfectly cromulent types from the AST that
are both a in isolation, but are actually different. They will have
different Unique values in their Name’s and come from different
implicit forall‘s. The question is what’s a good way to communicate
this to the user?

This is partly a “user interface” question, and on the side a “given
an ideal UI, do we have the necessary info the GHC API?”

If it helps, I could probably spend some time making an isolated
module that uses the GHC API to compile a file and then report these
types.

Ciao!
​
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-devs/attachments/20161026/7052867b/attachment-0001.html>


More information about the ghc-devs mailing list