Opened 15 months ago

Last modified 11 months ago

#12030 new feature request

GHCi Proposal: Display (Data.Kind.)Type instead of *

Reported by: Iceland_jack Owned by: johnleo
Priority: normal Milestone:
Component: GHCi Version: 8.1
Keywords: TypeInType Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description (last modified by Iceland_jack)

This is premature but what the darn,

>>> :kind Maybe
Maybe :: Type -> Type
>>> :kind StateT
StateT :: Type -> (Type -> Type) -> Type -> Type
>>> :kind Eq
Eq :: Type -> Constraint

>>> :info Functor
class Functor (f :: Type -> Type) where
...

* throws students off in my experience, makes it seem scarier than it is. Symbols are harder to search for and understand without documentation, Type on the other hand is descriptive.

There are arguments against:

  1. It's a recent feature that is subject to change.
  2. * is established in questions online, educational material, logs and blogs.
  3. Type is not in scope by default: user cannot query GHCi.

* is established and searching for “Haskell asterisk” yields a lot resources but ‘*’ is also a wildcard in Google and ignored by GitHub. With time Type would be a good search term but currently it's chicken-and-the-egg.

Previous versions of GHCi error on :kind * and :info * only shows multiplication so that wouldn't be a huge difference but we can qualify by default:

>>> :kind Maybe
Maybe :: Data.Kind.Type -> Data.Kind.Type
>>> :kind StateT
StateT :: Data.Kind.Type -> (Data.Kind.Type -> Data.Kind.Type) -> Data.Kind.Type -> Data.Kind.Type
>>> :kind Eq
Eq :: Data.Kind.Type -> Constraint

>>> :info Functor
class Functor (f :: Data.Kind.Type -> Data.Kind.Type) where
...

or display * normally and only when TypeInType is set do we display Type. I don't love it (and love GHC.Types.Type slightly less) but there is a precedent for unqualified names, browsing the Prelude for example:

($) ::
  forall (r :: GHC.Types.RuntimeRep) a (b :: TYPE r).
  (a -> b) -> a -> b
undefined ::
  forall (r :: GHC.Types.RuntimeRep) (a :: TYPE r).
  GHC.Stack.Types.HasCallStack =>
  a

If the consensus is that this will happen sometime down the line consider that each passing release means many more books and blog posts get written using *.

I wasn't planning on resulting to scare tactics but here we are...


If needed a migration plan can be drafted like the Semigroup/FTP/AMP/BBP/MonadFail/expanding Float/... proposals, possibly culminating in Type fully replacing * and being imported by default. I'm sure there are some further reaching consequences to this and better arguments against.

Change History (3)

comment:1 Changed 12 months ago by Iceland_jack

Description: modified (diff)

comment:2 Changed 11 months ago by johnleo

Comments by Richard Eisenberg (goldfire), copied from https://ghc.haskell.org/trac/ghc/ticket/12029:

  • * is not (yet) deprecated. While I did work with the larger community to come up with the name Type, I don't recall getting specific support for deprecating *. I do think this is a good direction of travel, but I don't think we should do this without more of a community mandate.
  • There are no kind synonyms in GHC 7.10 or below. Thus, according to the three-release policy (which isn't a formal operating policy of GHC, I don't think) we should wait until 8.4 before starting to deprecate *.
  • If the community agrees on moving away from *, we could add warnings about * to -Wcompat.
  • If the community agrees on moving away from *, we could also start changing the pretty-printer to use Type instead of *. This is not to be done lightly, however. There are several issues here:
    • Blogs, textbooks, etc., have used * for a long time. Furthermore, kinds are hard for newcomers to understand. Changing GHC's output will make this harder.
    • Until 8.4 comes out, it will be hard for a library author to discover that * is the right way to spell Type that is compatible with three releases.
    • The use of * as a kind is enshrined in the Haskell Reports. These Reports do not specify the error/warning behavior of a compiler, and so this change is not exactly a deviation from a standard. But it continues to make GHC seem as if it's drifting away from the standard with little remorse.
  • I personally think we should wait at least 5-6 years before formally disposing of *.

I will create a proposal in https://github.com/ghc-proposals/ghc-proposals in the near future to start a conversation.

comment:3 Changed 11 months ago by johnleo

Owner: set to johnleo
Note: See TracTickets for help on using tickets.