Re: Differences between (O)Caml and SML

From: Xavier Leroy (Xavier.Leroy@inria.fr)
Date: Sun Aug 15 1999 - 14:48:23 MET DST


Date: Sun, 15 Aug 1999 14:48:23 +0200
From: Xavier Leroy <Xavier.Leroy@inria.fr>
To: Shmulik Regev <shmul@iname.com>, caml-list@inria.fr
Subject: Re: Differences between (O)Caml and SML
In-Reply-To: <199907311223.PAA29780@alpha.netvision.net.il>; from Shmulik Regev on Sat, Jul 31, 1999 at 03:26:20PM +0300

> Can anyone point out the differences between OCaml to SML, other then the
> obvious object system.

I'm assuming you're interested in differences in the two languages.
(If you're interested in a comparison of implementations, please name
an implementation of SML and I'll explain why the OCaml implementation
is superior :-)).

There are numerous small syntactic differences due to the fact that
SML and Caml forked off the original LCF ML developed at Edinburgh in
the early '80s, and underwent separate development since.

In the core language, the most significant difference is the treatment
of record types. Caml treats record types exactly like sum types:
record types must be declared before use; they are compared by name
instead of by structure; and you can't conveniently use the same label
in two record types in the same module. The latter ensures that the
type of a record access can always be inferred.

SML treats records like a generalization of tuples: records can be
built without prior declaration of the record type; record types are
compared by structure; labels can thus belong to several types at
once, at the cost of some problems with type inference. For instance,
the function

        fun x -> x.lbl

has only one possible type in Caml, as determined by the most recent
declaration of a record type with a "lbl" label, while in SML this
function has many different types

        {lbl:'a; <other labels>} -> 'a

for every set of labels <other labels>. If the context doesn't allow
to determine more precisely the type of the function, it is rejected
by the type-checker.

Similarly, SML allows limited overloading on arithmetic operators, so
that one can use "+" to refer either to integer addition or to
floating-point addition. This is often convenient, but causes
functions where the overloading cannot be resolved from the context to
be rejected (e.g. fun x -> x + x can have two types, int->int
and float->float, and is thus rejected if the context doesn't force
one of the two types). Some versions of Caml had overloading as well,
but Caml Light and Objective Caml don't, in order to avoid this type
inference problem.

Concerning the module system, there used to be deep theoretical
differences between SML 90 and OCaml, with SML 90 being based on
structure sharing while OCaml only has type sharing. Structure
sharing was abandoned in SML 97, however, so the two module systems
are now very close. SML 97 has both "transparent" and "opaque"
signature constraints, while OCaml's signature constraints are always
opaque, but this is no big deal as the effect of a transparent
constraint can be achieved by an opaque constraint by a signature
having more manifest type specifications.

Compared with SML'97, OCaml also has a few rarely used extra features
such as higher-order functors and signature polymorphism (the New
Jersey implementation of SML also has higher-order functors, although
of a slightly different flavor than OCaml's).

These are the main differences I can remember. If anyone sees
significant differences that I forgot, please post to this list.

- Xavier Leroy



This archive was generated by hypermail 2b29 : Sun Jan 02 2000 - 11:58:24 MET