From: Pierre Weis <pierre.weis@inria.fr>
To: skaller@ozemail.com.au (John Max Skaller)
Cc: pierre.weis@inria.fr, brogoff@speakeasy.net, caml-list@inria.fr
Subject: Re: [Caml-list] syntax of private constructors in CVS version
Date: Tue, 8 Jul 2003 00:31:16 +0200 (MET DST) [thread overview]
Message-ID: <200307072231.AAA14343@pauillac.inria.fr> (raw)
In-Reply-To: <3F04178B.6050107@ozemail.com.au> from John Max Skaller at "Jul 3, 103 09:46:19 pm"
> > As you should already know, usual sum and product types in Caml
> > correspond to the mathematical notion of free algebraic data
> > structures. This is fairly useful and allows the modelization of a lot
> > of common data structures in practical programming
> > situations. However, besides the free algebra structures,
> > mathematicians use a lot of non-free algebras (so-called structures
> > defined via generators and relations). Private types aim at giving a
> > way to modelize those non-free structures. Equivalenetly, you can
> > think of private types as providing a way to implement types equipped
> > with invariants, quotient structures (i.e. sets of equivalence classes
> > for some equivalence relation on a free algebra), or data types with
> > canonical normal forms.
>
>
> Well said. If I may add: this can already be done using
>
> classes, or abstraction of modules. However these tools
> are much *too* heavyweight, because they also hide the
> algebraic structure of the types completely.
>
> The user then must provide all the accessor functions,
> for example, instead of using record labels or pattern matching.
Absolutely. That's just the idea behind private types: ensure the
necessary invariants but keep the ease of rpogramming new functions
via pattern matching (and save the burden to provide all the
accessors).
> For immutable values, establishing an invariant at construction
> time is enough to ensure the invariant is preserved: therefore,
> it is enough to make construction abstract to ensure all values
> of the type satisfy the invariants.
Exactly.
> Just for interest, this is not the case for mutable objects,
> for example:
>
> type rational = private { mutable x: float; mutable y: float };
> ...
> let mess_up_invariant (z:rational) = z.y <- 0.0
>
> Be interested to know the treatment of records with mutable fields.
> Are they permitted? Or are the mutators disallowed?
Records with mutable fields are permitted. Mutators explicitely exported
as functions are allowed, other mutations are forbidden.
I once wrote a lot of arithmetics and helped people writing core
arithmetics libraries for Caml. I always thought we had a major flaw
in the design of the library, due to type abstraction: we were
constantly oscillating between two conflicting attitudes; on the one
hand, using abstract data types all over the place to preserve
invariants and on the other hand turning to concrete types, not to be
forced to code everything ourself within the module implementing the
ADT.
I think private types are also a good answer to the
problem. Implementation of rational numbers would use a record with
mutable fields, and define a rational creation and a normalization
functions, preserving invariants:
type rat = {
mutable numerator : int;
mutable denominator : int;
};;
let rec mk_rat n d =
if d = 0 then failwith "mk_rat: null denominator" else
if d < 0 then mk_rat (- n) (- d) else
{ numerator = n; denominator = d};;
(* Left as an exercise *)
let gcd n m = 1;;
let normalize_rat r =
let g = gcd r.numerator r.denominator in
if g <> 1 then begin
r.numerator <- r.numerator / g;
r.denominator <- r.denominator / g
end;;
Then interface of the module would abstract creation and mutation:
type rat = private {
mutable numerator : int;
mutable denominator : int;
};;
val mk_rat : int -> int -> rat;;
val normalize_rat : rat -> unit;;
This way, there is no need to define access to numerator and
denominator, or even to write printing functions: the user can write
them easily:
open Rat;;
let print_rat r =
normalize_rat r;
match r with
| { numerator = n; denominator = d} -> Printf.printf "%d/%d" n d;;
Also, any attempt to mutate a rational is now statically rejected by
the typechecker:
let r = mk_rat 1 2 in
r.numerator <- 4;
Cannot assign field numerator of private type Rat.rat.
Hence, in a sense, private types can also serve as a primitive way to
turn a mutable data type into an immutable one outside its defining
implementation, provided that no mutating functions are exported.
A small addition for the language, a big step for the programmer :)
Pierre Weis
INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://pauillac.inria.fr/~weis/
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
next prev parent reply other threads:[~2003-07-07 22:31 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-06-27 20:50 Shaddin Doghmi
2003-06-27 21:15 ` brogoff
2003-06-27 22:10 ` Shaddin Doghmi
2003-06-28 2:24 ` brogoff
2003-06-30 18:39 ` Pierre Weis
2003-06-30 19:00 ` Chris Hecker
2003-06-30 21:36 ` brogoff
2003-07-01 10:47 ` Pierre Weis
2003-07-01 7:43 ` Hendrik Tews
2003-07-01 10:37 ` Yaron M. Minsky
2003-07-01 10:51 ` Yaron M. Minsky
2003-07-01 17:05 ` Pierre Weis
2003-07-01 17:20 ` brogoff
2003-07-03 11:46 ` John Max Skaller
2003-07-07 22:31 ` Pierre Weis [this message]
2003-07-13 9:11 ` John Max Skaller
2003-07-15 8:02 ` Laurent Vibert
2003-07-15 8:22 ` Pierre Weis
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200307072231.AAA14343@pauillac.inria.fr \
--to=pierre.weis@inria.fr \
--cc=brogoff@speakeasy.net \
--cc=caml-list@inria.fr \
--cc=skaller@ozemail.com.au \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox