Opened 3 years ago

Closed 14 months ago

#12030 closed feature request (fixed)

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

Reported by: Iceland_jack Owned by: johnleo
Priority: normal Milestone: 8.6.1
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 =>

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 (4)

comment:1 Changed 3 years ago by Iceland_jack

Description: modified (diff)

comment:2 Changed 3 years ago by johnleo

Comments by Richard Eisenberg (goldfire), copied from

  • * 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 in the near future to start a conversation.

comment:3 Changed 3 years ago by johnleo

Owner: set to johnleo

comment:4 Changed 14 months ago by RyanGlScott

Milestone: 8.6.1
Resolution: fixed
Status: newclosed

My understanding is that the -XNoStarIsType extension gives you exactly what you seek here, since that displays * as Type in GHCi:

GHCi, version  :? for help
Loaded GHCi configuration from /home/rgscott/.ghci
λ> :kind Int
Int :: *
λ> :set -XNoStarIsType 
λ> :kind Int
Int :: Type

As such, I'm opting to close this.

(There's still an ongoing discussion about whether -XNoStarIsType should be the default, but that's a separate matter.)

Note: See TracTickets for help on using tickets.