caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: John Prevost <j.prevost@gmail.com>
To: Ocaml Mailing List <caml-list@inria.fr>
Subject: Re: [Caml-list] Functors and classes
Date: Tue, 3 Aug 2004 19:24:51 -0400	[thread overview]
Message-ID: <d849ad2a040803162470ad4f16@mail.gmail.com> (raw)
In-Reply-To: <Pine.LNX.4.58.0408031500000.22016@shell2.speakeasy.net>

GOT IT!

The trick is to provide a cast operation from the original module,
which can then be used by the functor.  The functor gets grumpy
because it doesn't have enough information (or perhaps smarts) to be
sure the type can be unified.  But the original creator surely does.

Find below the complete source--I separated things up in some
semblance of the modules you'd expect to find in wild .ml and .mli
files, just to be sure that doesn't break anything.  :)

The best part is that even though the functor has to go through "toss"
to get to the known methods of a connection, the module that uses the
functor knows the full identity of the type, and can access all
methods (and use other functions that work on the type) of the
original object--preserving extensibility.


module Things =                         (* Things.ml *)
  (struct
    class type base_connection =
      object
        method a : int
      end

    module type Thing_T =
      sig
        type connection
        val connect : unit -> connection
        val toss : connection -> base_connection
      end

    module type Thing_Pool_T =
      sig
        type connection
        val connect : unit -> connection
        val test : connection -> int
      end

    module Thing_Pool (Thing : Thing_T) :
        Thing_Pool_T with type connection = Thing.connection =
      struct
        type connection = Thing.connection
        let connect () = Thing.connect ()
        let test c = (Thing.toss c)#a + 1
      end
  end : sig                             (* Things.mli *)
    class type base_connection =
      object
        method a : int
      end

    module type Thing_T =
      sig
        type connection
        val connect : unit -> connection
        val toss : connection -> base_connection
      end

    module type Thing_Pool_T =
      sig
        type connection
        val connect : unit -> connection
        val test : connection -> int
      end

    module Thing_Pool : functor (Thing : Thing_T) ->
      Thing_Pool_T with type connection = Thing.connection
  end)

(* database package to be pooled *)

module Thing_Test =                     (* Thing_Test.ml *)
  (struct
    class connection =
      object
        method a = 1
        method b = 2
      end
    let connect () = new connection
    let toss c = (c :> Things.base_connection)
  end : sig                             (* Thing_Test.mli *)
    class connection :
      object
        method a : int
        method b : int
      end
    val connect : unit -> connection
    val toss : connection -> Things.base_connection
  end)

(* package using the pool *)

module Program =                        (* Program.ml *)
  struct
    open Things
      
    module X = Thing_Pool(Thing_Test)
        
    let x = X.connect ()
    let a = x#a
    let b = x#b
  end

-------------------
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-08-03 23:24 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-08-03 12:02 Richard Jones
2004-08-03 12:10 ` Richard Jones
2004-08-03 13:17   ` Richard Jones
2004-08-03 15:06     ` John Prevost
2004-08-03 15:12       ` Richard Jones
2004-08-03 15:27         ` John Prevost
2004-08-03 15:28           ` John Prevost
2004-08-03 19:57             ` brogoff
2004-08-03 22:05               ` brogoff
2004-08-03 23:24                 ` John Prevost [this message]
2004-08-03 15:50       ` Richard Jones
2004-08-03 16:23         ` John Prevost
2004-08-03 16:42           ` Richard Jones

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=d849ad2a040803162470ad4f16@mail.gmail.com \
    --to=j.prevost@gmail.com \
    --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).