[Haskell-cafe] New type of ($) operator in GHC 8.0 is problematic

Manuel Gómez targen at gmail.com
Sat Feb 6 18:14:56 UTC 2016


On Sat, Feb 6, 2016 at 12:42 PM, Edward Kmett <ekmett at gmail.com> wrote:
> The primitives that GHC uses to implement arrays, references and the like
> live in #. We then wrap them in something in * before exposing them to the
> user, but you can shave a level of indirection by knowing what lives in #
> and what doesn't.

Yes!  Let’s not forget, of course, that these (or similar) have been
in GHC for many, many years, right in the Prelude:

```
> :i Int Char Float Double IO Integer
data Int = GHC.Types.I# GHC.Prim.Int#
data Char = GHC.Types.C# GHC.Prim.Char#
data Float = GHC.Types.F# GHC.Prim.Float#
data Double = GHC.Types.D# GHC.Prim.Double#
newtype IO a
  = GHC.Types.IO (GHC.Prim.State# GHC.Prim.RealWorld
                  -> (# GHC.Prim.State# GHC.Prim.RealWorld, a #))
data Integer
  = integer-gmp-1.0.0.0:GHC.Integer.Type.S# !GHC.Prim.Int#
  | integer-gmp-1.0.0.0:GHC.Integer.Type.Jp# {-# UNPACK
#-}integer-gmp-1.0.0.0:GHC.Integer.Type.BigNat
  | integer-gmp-1.0.0.0:GHC.Integer.Type.Jn# {-# UNPACK
#-}integer-gmp-1.0.0.0:GHC.Integer.Type.BigNat
```

Stepping outside the Prelude, yet well within beginner territory,
brings even more fun:

```
> :i Map Set
data Map k a
  = containers-0.5.6.2:Data.Map.Base.Bin {-# UNPACK
#-}containers-0.5.6.2:Data.Map.Base.Size
                                         !k
                                         a
                                         !(Map k a)
                                         !(Map k a)
  | containers-0.5.6.2:Data.Map.Base.Tip
data Set a
  = containers-0.5.6.2:Data.Set.Base.Bin {-# UNPACK
#-}containers-0.5.6.2:Data.Set.Base.Size
                                         !a
                                         !(Set a)
                                         !(Set a)
  | containers-0.5.6.2:Data.Set.Base.Tip
```

Unboxed types, the UNPACK pragma, references to GHC.Prim (which easily
lead to confusing exploration), unboxed tuples, an unboxed State
monad, RealWorld, bang patterns, unexported constructors,
implementation details for abstract types… all of them available right
from the prompt of the Prelude using the main tool for exploratory
learning that beginners rely on.

I’m not saying this is a good thing and I’m not saying this should be
fixed.  I’m not even saying this is comparable to the situation with $
and I’m likewise not saying presenting these concepts to beginners
should be thought of as comparable to presenting levity polymorphism
to beginners.  It is nonetheless relevant context to this discussion;
the Prelude has always had concepts unfriendly to beginners readily
available, and Haskell beginner teachers have always had to work
around these issues.  Students have always asked about these things.

> But even if you never care about #, Int, Double, etc. are of kind *,
> Functors are of kind * -> *, etc. so to talk about the type of types at all
> you need to be able to talk about these concepts at all with any rigor, and
> to understand why Maybe Maybe isn't a thing.

In my personal teaching experience, it is extremely helpful to discuss
kinds in the first introduction of type constructors, after covering
types with no parameters.  This is especially helpful in discussing
how the hierarchy leading to Monad works, and why things like
«instance Functor (Tree Int) where …» don’t make sense and why
«instance Functor Tree where …» must be parametric in the type of the
thing in the tree, which in turn motivates a lot more discussion.

Teaching kinds is teaching Haskell basics.  It is not an advanced
topic.  It ought to be covered near the very first lessons on Haskell
for absolute beginners.


More information about the Haskell-Cafe mailing list