caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
To: caml-list@inria.fr
Subject: [Caml-list] Encoding objects using recursive first-class modules
Date: Fri, 18 Feb 2011 15:44:43 +0900 (JST)	[thread overview]
Message-ID: <20110218.154443.07636736.garrigue@math.nagoya-u.ac.jp> (raw)

Dear Camlers,

There has been some excitement about the possibilities of first-class
modules.
One application is to use them as objects, as is already done in the
amthing project (using interesting syntactic sugar).
This may interest some people that the relation to objects doesn't
stop at the concrete object level: combining them with recursive
modules, one can also easily encode classes, with virtual methods and
inheritance.
The basic idea is to turn classes (or rather "traits") into functors
from the final object to a list of methods.
Here is a bit of code demonstrating this.
This code is rather verbose, but using 3.13 features and amthing
syntax it can be made much lighter.

Jacques Garrigue

(* Signature for points, all methods must be functions *)
module type Point = sig
  val get_x : unit -> int
  val move : int -> unit
end

(* The Point class, with state x *)
(* Needs to be a functor, to allow creating new state *)
module PointF(X : sig end) = struct
  let x = ref 0
  let get_x () = !x
  let move d = x := !x + d
end

(* Create a new point *)
let new_point () = (module PointF(struct end) : Point)

(* Signature for the Show trait *)
module type Show = sig
  val show : unit -> string
end

(* Implementation for the Show trait *)
module ShowF(P : Point) = struct
  let show () = Printf.sprintf "x = %i" (P.get_x ())
end

(* Signature for the ShowPoint class *)
module type ShowPoint = sig include Point include Show end

(* ShowPoint class *)
module ShowPointF(P : ShowPoint) = struct
  include PointF(P)
  include ShowF(P)
end

(* Create a new ShowPoint object, by tying the knot *)
let new_showpoint () =
  let module M = struct
    module rec SP : ShowPoint = ShowPointF(SP)
  end in (module M.SP : ShowPoint)

(* Play with it *)
let sp = new_showpoint ()
let a =
  let module SP = (val sp : ShowPoint) in
  SP.move 2; SP.show ()

(* One can coerce to a supertype *)
let sp_as_p = (module (val sp : ShowPoint) : Point)


                 reply	other threads:[~2011-02-18  6:45 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20110218.154443.07636736.garrigue@math.nagoya-u.ac.jp \
    --to=garrigue@math.nagoya-u.ac.jp \
    --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).