Primitive types and Prelude shenanigans

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? Some of my other natural thoughts along these lines are positive reals and rationals, and nonzero integers. Rationals I have an idea that they might be similar to natural numbers and nonzero integers, though the nonzero and positive reals pose some nasty problems (try underflow). Would such machinations be useful to anyone else? 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? 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. Cheers, Bill

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

On Mon, Feb 12, 2001 at 11:00:02AM +0100, Marcin 'Qrczak' Kowalczyk wrote:
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.
I'm aware natural numbers are not a primitive data type within Haskell; I had the idea in mind that for my own experimentation I might add them. On Mon, Feb 12, 2001 at 11:00:02AM +0100, Marcin 'Qrczak' Kowalczyk wrote:
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.
Perhaps I should clarify my intentions: The various symbols for integer literals all uniformly denote the values fromInteger #n where #n is some monotype or other. What I had in mind was (again, for my own wicked purposes) treating specially the symbols 0 and 1 so that the implicit coercions going on are for the type classes where additive and multiplicative identities exist, then overloading the positive symbols so that the implicit coercion is instead fromNatural, and then leaving the negative symbols (largely) as they are. This is obviously too radical for me to propose it as anything, I intend to only do it as an experiment or perhaps for my own usage (though if others find it useful, they can have it). On Mon, Feb 12, 2001 at 11:00:02AM +0100, Marcin 'Qrczak' Kowalczyk wrote:
Modules with names beginning with Prel define approximately everything what Prelude includes and everything with magic support in the compiler.
I've not only already found these, but in attempting to substantially alter them I've run into the trouble below: On Mon, Feb 12, 2001 at 11:00:02AM +0100, Marcin 'Qrczak' Kowalczyk wrote:
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
The magic part I don't seem to get is that moving the definition of Bool around and also changing the types of various things assumed to be Bool causes things to break. The question seems to be of figuring out what depends on it being where and how to either make it more flexible or accommodate it. On Mon, Feb 12, 2001 at 11:00:02AM +0100, Marcin 'Qrczak' Kowalczyk wrote: [useful info not needing a response snipped] On Mon, 12 Feb 2001, William Lee Irwin III wrote:
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.
On Mon, Feb 12, 2001 at 11:00:02AM +0100, Marcin 'Qrczak' Kowalczyk wrote:
Inside the compiler, not in libraries.
I had in mind looking within the compiler, actually. Where in the compiler? It's a big program, it might take me a while to do an uninformed search. I've peeked around a little bit and not gotten anywhere. Cheers, Bill

On Mon, 12 Feb 2001, William Lee Irwin III wrote:
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.
On Mon, Feb 12, 2001 at 11:00:02AM +0100, Marcin 'Qrczak' Kowalczyk wrote:
Inside the compiler, not in libraries.
On Mon, Feb 12, 2001 at 02:38:25PM -0800, William Lee Irwin III wrote:
I had in mind looking within the compiler, actually. Where in the compiler? It's a big program, it might take me a while to do an uninformed search. I've peeked around a little bit and not gotten anywhere.
If anyone else is pursuing thoughts along the same lines as I am (and I have suspicions), TysWiredIn.lhs appears quite relevant to the set of primitive data types, though there is no obvious connection to the module issue (PrelBase.Bool vs. Foo.Bool). PrelMods.lhs appears to shed more light on that issue in particular. $TOP/ghc/compiler/prelude/ was the gold mine I encountered. In DsExpr.lhs, I found: ] \subsection[DsExpr-literals]{Literals} ] ... ] We give int/float literals type @Integer@ and @Rational@, respectively. ] The typechecker will (presumably) have put \tr{from{Integer,Rational}s} ] around them. and following this pointer, I found TcExpr.lhs (lines 213ff) had more material of interest. While I can't say I know how to act on these "discoveries" (esp. since I don't really understand OverloadedIntegral and OverloadedFractional's treatment(s) yet), perhaps this might be useful to others interested in ideas along the same lines as mine. Happy hacking, Bill
participants (2)
-
Marcin 'Qrczak' Kowalczyk
-
William Lee Irwin III