caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Michael Vanier <mvanier@cs.caltech.edu>
To: caml-list@inria.fr
Subject: [Caml-list] extensible records?
Date: Thu, 26 Feb 2004 16:45:57 -0800 (PST)	[thread overview]
Message-ID: <20040227004557.C85CE9BBA2@orchestra.cs.caltech.edu> (raw)


Hi everyone!

I'm having a problem figuring out how to implement something in ocaml, and
I'd like to solicit advice.  I'm writing a little dynamically-typed language
in ocaml, and I want to be able to add new types to the language without
having to add new primitive types to the system.  So, for instance, my basic
type definition looks something like this:

    type data =
        Int of int
      | Float of float
      | ...

Now let's say I want to add a type for files.  I don't want this to be a type
at the same level as ints or floats, because I want users to be able to add
their own types to the language without hacking the core type definition
(which is possible in, for instance, python).  So my ideal solution would be
something like this (not real ocaml code):

    (* types.mli *)
    type data =
        Int of int
      | Float of float
      | ...
      | Extension of extension

    type extension = []  (* nothing yet, not valid ocaml *)

    (* files.mli *)
    extension File of out_channel  (* not valid ocaml *)

    (* files.ml *)
    let close (d : data) =
      match data with
        Extension ext ->
          (match ext with
               File f -> (* close the file *)
             | _ -> raise (Failure "invalid type"))
        | _ -> raise (Failure "invalid type")

I can see two ways I can do this already, but both involve abusing the
exception system.  Way 1:

    (* types.mli *)
    type data =
        Int of int
      | Float of float
      | ...
      | Extension of unit -> unit


    (* files.ml *)
    exception File of out_channel

    let open_file filename =
      (* open the file as new_file *)
      raise (File new_file)

    let close (d : data) =
      match data with
        Extension ext ->
          try ext ()
          with ext' ->
            (match ext' with 
                File f -> (* close the file *)
              | _ -> raise (Failure "invalid type"))
        | _ -> raise (Failure "invalid type")

Aside from abusing the exception system, I've been told that this would be
slow due to the exception handling overhead.  A more direct way would be:

    (* types.mli *)
    type data =
        Int of int
      | Float of float
      | ...
      | Extension of exn


    (* files.ml *)
    exception File of out_channel

    let close (d : data) =
      match data with
        Extension ext ->
          (match ext with 
              File f -> (* close the file *)
            | _ -> raise (Failure "invalid type")))
        | _ -> raise (Failure "invalid type")

This would (I think) work, and wouldn't involve excessive overhead.  But
really, all I'm doing is abusing the fact that exceptions are the one kind of
extensible record type built in to ocaml.  What I want to know is: is there a
better way to do this?

I thought of using polymorphic variant types, but my (limited) understanding
is that you either declare all possible variants straight up in the .mli file
(which totally defeats my purpose) or you don't declare anything and let the
compiler infer the type (which I don't know how to write into a .mli file).
If this can be done with polymorphic variants, how would I do it?
Alternatively, if this can be done with objects, how would I do it?  Or
should I just stick with abusing exceptions?

Cheers,

Mike

-------------------
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


             reply	other threads:[~2004-02-27  0:46 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-02-27  0:45 Michael Vanier [this message]
2004-02-27  1:04 ` Kenneth Knowles
2004-02-27  8:39 ` Aleksey Nogin
2004-02-27  8:39 ` Nicolas Cannasse
2004-02-27 11:17 ` Alexander S. Usov

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=20040227004557.C85CE9BBA2@orchestra.cs.caltech.edu \
    --to=mvanier@cs.caltech.edu \
    --cc=caml-list@inria.fr \
    /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;
as well as URLs for NNTP newsgroup(s).