Primitive types and Prelude shenanigans

Marcin 'Qrczak' Kowalczyk mk167280@students.mimuw.edu.pl
Mon, 12 Feb 2001 11:00:02 +0100 (CET)


On Mon, 12 Feb 2001, William Lee Irwin III wrote:

> It seems to me that some additional primitive types would be useful,
> most of all a natural number type corresponding to an arbitrary-
> precision unsigned integer. Apparently Integer is defined in terms
> of something else in the GHC Prelude, what else might be needed to
> define it?

It depends on the implementation and IMHO it would be bad to require
a particular implementation for no reason. For example ghc uses the gmp
library and does not implement Integers in terms of Naturals; gmp handles
negative numbers natively.

> Some of my other natural thoughts along these lines are positive
> reals and rationals, and nonzero integers.

You can define it yourself by wrapping not-necessarily-positive types
if you feel the need. Most of the time there is no need because Haskell
has no subtyping - they would be awkward to use together with present
types which include negative numbers.

> Further down this line, I've gone off and toyed with Bool, and
> discovered GHC doesn't like it much. Is there a particular place within
> GHC I should look to see how the primitive Boolean type, and perhaps
> other types are handled?

Modules with names beginning with Prel define approximately everything
what Prelude includes and everything with magic support in the compiler.

PrelGHC defines primops that are hardwired in the compiler, and PrelBase
is a basic module from which most things begin. In particular Bool is
defined there as a regular algebraic type
    data Bool = False | True

Types like Int or Double are defined in terms of primitive unboxed types
called Int# and Double#. They are always evaluated and are not like other
Haskell types: they don't have the kind of the form * or k1->k2 but a
special unboxed kind, their values don't include bottom. You can't have
[Int#] or use Prelude.id :: Int# -> Int#. They can be present in data
definitions and function arguments and results.

There is more of primitive stuff: primops like +# :: Int# -> Int# -> Int#,
primitive array types, unboxed tuples, unboxed constants. There is a paper
about it but I don't have the URL here. They are also described in GHC
User's Guide.

They are not portable at all. Other Haskell implementations may use very
different implementation techniques.

In ghc they exist primarily to make it easy to express optimizations -
these types occur all the time during internal transformations of the
module being opzimized - laziness is optimized away when possible. They
are often present in .hi files when a function has been split into worker
and wrapper, so that code using the module can refer to the worker using
primitive types directly instead of allocating every number on the heap.

They are also exposed to the programmer (who imports GlaExts) who really
wants to hack with them manualy. They don't have nice Haskell properties
of other types (fully polymorphic operations don't work on these types) so
I would not expect such thing to appear officially in the Haskell
definition.

> I'd also like to see where some of the magic behind the typing of
> various other built-in constructs happens, like list comprehensions,
> tuples, and derived classes.

Inside the compiler, not in libraries.

-- 
Marcin 'Qrczak' Kowalczyk