Version française
Home     About     Download     Resources     Contact us    

This site is updated infrequently. For up-to-date information, please visit the new OCaml website at

Browse thread
[Caml-list] Polymorphism and the "for" loop
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: David Brown <caml-list@d...>
Subject: Re: [Caml-list] Polymorphism and the "for" loop
On Fri, Oct 22, 2004 at 08:38:49AM +0100, Jon Harrop wrote:

> I've been wondering about this recently: how do the compilers store types 
> which contain "unit". For example, if we have a tree:
> type 'a 'b tree = Leaf of 'a | Node of 'b * 'a 'b tree * 'a 'b tree
> Does a "unit unit tree" take up less space than a "int int tree"?

Each of the types 'Leaf', or Node will always take the same amount of
space, not counting the header (which is 1 word before the block):  A leaf
will be 1 word, and a Node will be 2 words.  The value passed around is
always a word, which fits in a pointer.

So a "unit unit tree" of the same shape takes up the same space as an "int
int tree".  However, if the type doesn't fit in a word, heap space will be
needed for the block.

In ocaml, (), the only value of type unit, is always represented as the
word '1'.

The unit type follows nicely from the pattern of n-tuples (pairs, triples,
4-typles, so why not 0-tuples).  The unit value is really a 0-tuple.  Since
the type is parameterized by 0 other types, there is only one unit type.

> The reason I'm asking is that it might be nice to generalise data structures 
> as much as possible and then specialise them using "unit" arguments.

But, the original discussion was concerning procedures that don't actually
return anything.  Without side-effects, procedures aren't useful, since
they can't do anything.  Since there are side effects, though, it is
meaningful to have a procedure that doesn't return any type.  The unit type
was created for this purpose.  If we created another type, say void, to
indicate a function that returned no value (a procedure), it would mostly
serve the same purpose as the unit type.  It might be possible to avoid
having a constructor for this type, but then it gets more difficult to
explicitly ignore values.  I think you would quickly get back to the same
place we are at now.

Perhaps 'unit' is fine for functions that don't return anything, and we
should come up with something different to pass in as the needed argument
to functions that don't need an argument.  You could always create

  type noarg = Noarg

another single-constructor type, and use noarg for functions that don't
really want an argument.  This would prevent you from calling this function
with the result of something that wasn't intended to return a value.

I guess my question is, for functions that takes unit, and returns unit,
what's really wrong with:

  f (g ())

The evaluation order is defined, although not necessarily meaningful.
Perhaps later I might want to come up with a value that gets passed from g
to f.


To unsubscribe, mail Archives:
Bug reports: FAQ:
Beginner's list: