Browse thread
[Caml-list] Functors and classes
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
| Date: | -- (:) |
| From: | John Prevost <j.prevost@g...> |
| Subject: | Re: [Caml-list] Functors and classes |
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