* [Caml-list] Module/functor question
@ 2004-03-14 19:05 ronniec95
2004-03-14 19:22 ` Yamagata Yoriyuki
0 siblings, 1 reply; 5+ messages in thread
From: ronniec95 @ 2004-03-14 19:05 UTC (permalink / raw)
To: caml-list
Hello
I'm trying to acheive the following effect in Ocaml that I should be
able to do but am getting very confused with modules and functors...
I have a set of classes all with the structure:-
class Foo {
Foo* create(std::string x);
std::string toXml(Foo*);
... /* Other methods */
int m_x;
std::string m_y;
}
and I have a template function
template<typename T>
void serialisetoxml(T* x) { printf("%s\n",x->toXml().c_str());}
int main()
{
Foo* f = new Foo(1,"hello");
serialisetoxml(f);
}
The effect I want to acheive is to have a function that takes any module
that has a toXml function defined and invokes it somewhere.
The closest I got was
(*serialise.mli*)
type t (* this doesn't work...*)
module type Serialise
sig
val create : Xml.xml -> t (*Using XML-Light here *)
val to_xml : t -> Xml.xml
end
(*foo.mli*)
type t = { x : int ; y:int }
module Make
sig
val create : Xml.xml -> t (*Using XML-Light here *)
val to_xml : t -> Xml.xml
end
(*foo.ml*)
type t = { x : int ; y:int }
module Make : Serialiser =
struct
let create (f: Xml.xml) = Xml.Element("Foo",[("x",string_of_int f.x);("y",f.y))])
let to_xml (foo : t) = ...
(* It thinks f is of type Serialiser.t and not Foo.t *)
end
(* main.ml *)
module Sender (C : Serialiser) =
struct
let serialisetoxml msg = print_string (Xml.to_string (C.as_xml msg))
end
(* was hoping for something like this *)
let _ = let m = module Sender(Foo.Make) in
m.serialisetoxml (Foo.Make (Xml.parse_from "..."));
but I cannot figure out how to declare Foo having a signature of
Serialiser and then use it in main somehow. Assume also that I have
lots of other modules which have same basic interface but additional
methods specific to the modules.
Any help appreciated.
Thanks,
Ronnie
--
-------------------
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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Module/functor question
2004-03-14 19:05 [Caml-list] Module/functor question ronniec95
@ 2004-03-14 19:22 ` Yamagata Yoriyuki
2004-03-14 23:46 ` ronniec95
0 siblings, 1 reply; 5+ messages in thread
From: Yamagata Yoriyuki @ 2004-03-14 19:22 UTC (permalink / raw)
To: ronniec95; +Cc: caml-list
From: ronniec95@lineone.net
Subject: [Caml-list] Module/functor question
Date: Sun, 14 Mar 2004 19:05:28 +0000
> but I cannot figure out how to declare Foo having a signature of
> Serialiser and then use it in main somehow. Assume also that I have
> lots of other modules which have same basic interface but additional
> methods specific to the modules.
You do not need to declare. Foo.Make will accept any module whose
signature is an *extension* of Serializer.
> (* was hoping for something like this *)
> let _ = let m = module Sender(Foo.Make) in
> m.serialisetoxml (Foo.Make (Xml.parse_from "..."));
By the way, a correct code would be
let _ =
let module M = Sender(Foo.Make) in
M.serialisetoxml (Foo.Make (Xml.parse_from "..."));
--
Yamagata Yoriyuki
-------------------
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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Module/functor question
2004-03-14 19:22 ` Yamagata Yoriyuki
@ 2004-03-14 23:46 ` ronniec95
2004-03-15 12:34 ` Andreas Rossberg
0 siblings, 1 reply; 5+ messages in thread
From: ronniec95 @ 2004-03-14 23:46 UTC (permalink / raw)
To: Yamagata Yoriyuki; +Cc: caml-list
On Mon, Mar 15, 2004 at 04:22:18AM +0900, Yamagata Yoriyuki wrote:
> From: ronniec95@lineone.net
> Subject: [Caml-list] Module/functor question
> Date: Sun, 14 Mar 2004 19:05:28 +0000
>
> > but I cannot figure out how to declare Foo having a signature of
> > Serialiser and then use it in main somehow. Assume also that I have
> > lots of other modules which have same basic interface but additional
> > methods specific to the modules.
>
> You do not need to declare. Foo.Make will accept any module whose
> signature is an *extension* of Serializer.
>
> > (* was hoping for something like this *)
> > let _ = let m = module Sender(Foo.Make) in
> > m.serialisetoxml (Foo.Make (Xml.parse_from "..."));
>
> By the way, a correct code would be
>
> let _ =
> let module M = Sender(Foo.Make) in
> M.serialisetoxml (Foo.Make (Xml.parse_from "..."));
>
> --
> Yamagata Yoriyuki
Thanks that helped a lot - well it does work! but I'm a bit puzzled by
the extra declarations I had to do...
I've copied the exact code below since it's not that long. I wonder
about header.mli which has 'type t=u' in it which was the only way of
getting it all to fit together. Why do I have to do that? Is there
another a more Ocaml way that I should be tackling this problem (I guess
a more design rather than implementation question...?)
Thanks for any ideas.
Ronnie
------- Code ----------
(*Header.mli*)
type u
module Make :
sig
type t = u
val as_xml : t -> Xml.xml
val create : Xml.xml -> t
end
(* A function to construct Header.u objects *)
val make : ?version:int -> ?msgtypeid:int -> string -> string -> string -> u
(*Header.ml*)
(* some utility functions *)
let datetimefmt = "%Y%m%dT%H%M%S"
let find_node name root =
let rec find (lst : Xml.xml list) res = match lst with
| [] -> if List.length res = 0
then failwith ("Node not found:" ^ name)
else res
| Xml.Element(id,_,_) as hd::tl when id = name -> find tl (hd::res)
| _::tl -> find tl res
in
find (Xml.children root) []
type u= { version : int; created : Calendar.t; environment : string; msgtypeid : int; msgtype : string; originatorid : string; machineid: string; }
(* OK I want everything to have this signature at least *)
module type Constructor =
sig
type t = u
val as_xml : t -> Xml.xml
val create : Xml.xml -> t
end
module Make : Constructor =
struct
type t = u (* why do I need this?*)
let as_xml d =
Xml.Element("Header",[
("MsgVersion",(string_of_int d.version));
("Created",(fun x -> Printer.CalendarPrinter.sprint
datetimefmt x)d.created);
("Environment",d.environment);
("MsgTypeId",(string_of_int d.msgtypeid));
("MsgType",d.msgtype)],
[Xml.Element("Originator",[
("OriginatorId",d.originatorid);
("MachineId",d.machineid)],[])])
let create (root:Xml.xml) : t =
let originator = List.hd (find_node "Originator" root) in
{ version = int_of_string(Xml.attrib root "MsgVersion");
created = ((fun x -> Printer.CalendarPrinter.from_fstring datetimefmt x)
(Xml.attrib root "Created"));
environment = Xml.attrib root "Environment";
msgtypeid = int_of_string(Xml.attrib root "MsgTypeId");
msgtype = Xml.attrib root "MsgType";
originatorid = Xml.attrib originator "OriginatorId";
machineid = Xml.attrib originator "MachineId"; }
end
let make ?(version = 1) ?(msgtypeid=1) msgtype originator env =
{ version = version; created = Calendar.now(); environment = env; msgtypeid = msgtypeid; msgtype = msgtype; originatorid = originator; machineid = Unix.gethostname(); }
(*****************************************
* main.ml - thanks to Yamagata Yoriyuki
*****************************************)
(* Don't like declaring this AGAIN! in main*)
module type Constructor =
sig
type t
val as_xml : t -> Xml.xml
val create : Xml.xml -> t
end
module MessageSender (C : Constructor) =
struct
let send msg = print_string (Xml.to_string (C.as_xml msg))
end
let _ =
let module M = MessageSender(Header.Make) in
M.send (Header.make "Header" "TestMessage" "DEV") (* this works now!!*)
-------------------
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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Module/functor question
2004-03-14 23:46 ` ronniec95
@ 2004-03-15 12:34 ` Andreas Rossberg
2004-03-15 16:20 ` ronniec95
0 siblings, 1 reply; 5+ messages in thread
From: Andreas Rossberg @ 2004-03-15 12:34 UTC (permalink / raw)
To: ronniec95; +Cc: caml-list
ronniec95@lineone.net wrote:
>
> I've copied the exact code below since it's not that long. I wonder
> about header.mli which has 'type t=u' in it which was the only way of
> getting it all to fit together. Why do I have to do that?
You don't have to, if you declare the types at the right places, i.e.
inside the modules. Actually, you don't need the local modules at all,
since compilation units are already modules. Here is the sketch of a
simplified version (not tested).
(* header.mli *)
type t
val as_xml : t -> Xml.xml
val create : Xml.xml -> t
val make : ?version:int -> ?msgtypeid:int ->
string -> string -> string -> t
(* header.ml *)
type t = { version : int;
created : Calendar.t;
environment : string;
msgtypeid : int;
msgtype : string;
originatorid : string;
machineid: string; }
let as_xml d = ...
let create (root:Xml.xml) : t = ...
let make ?(version = 1) ?(msgtypeid=1) msgtype originator env = ...
(* main.ml *)
module type CONSTRUCTOR =
sig
type t
val as_xml : t -> Xml.xml
val create : Xml.xml -> t
end
module MessageSender (C : CONSTRUCTOR) =
struct
let send msg = print_string (Xml.to_string (C.as_xml msg))
end
let _ =
let module M = MessageSender(Header) in
M.send (Header.make "Header" "TestMessage" "DEV")
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
-------------------
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
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Module/functor question
2004-03-15 12:34 ` Andreas Rossberg
@ 2004-03-15 16:20 ` ronniec95
0 siblings, 0 replies; 5+ messages in thread
From: ronniec95 @ 2004-03-15 16:20 UTC (permalink / raw)
To: Andreas Rossberg; +Cc: caml-list
Thanks for that. It's all kind of starting to make sense now!!
I'll experiment a little more and hopefully should be able to get some buyin
at work for using Ocaml for our trading applications. Now the messaging
is working, along with XML transforms (thanks to all who helped). Just the
DB to do.....
Ronnie
>-- Original Message --
>Date: Mon, 15 Mar 2004 13:34:14 +0100
>From: Andreas Rossberg <rossberg@ps.uni-sb.de>
>To: ronniec95@lineone.net
>CC: caml-list@inria.fr
>Subject: Re: [Caml-list] Module/functor question
>
>
>ronniec95@lineone.net wrote:
>>
>> I've copied the exact code below since it's not that long. I wonder
>> about header.mli which has 'type t=u' in it which was the only way of
>> getting it all to fit together. Why do I have to do that?
>
>You don't have to, if you declare the types at the right places, i.e.
>inside the modules. Actually, you don't need the local modules at all,
>since compilation units are already modules. Here is the sketch of a
>simplified version (not tested).
>
> (* header.mli *)
> type t
> val as_xml : t -> Xml.xml
> val create : Xml.xml -> t
> val make : ?version:int -> ?msgtypeid:int ->
> string -> string -> string -> t
>
> (* header.ml *)
> type t = { version : int;
> created : Calendar.t;
> environment : string;
> msgtypeid : int;
> msgtype : string;
> originatorid : string;
> machineid: string; }
> let as_xml d = ...
> let create (root:Xml.xml) : t = ...
> let make ?(version = 1) ?(msgtypeid=1) msgtype originator env = ...
>
> (* main.ml *)
> module type CONSTRUCTOR =
> sig
> type t
> val as_xml : t -> Xml.xml
> val create : Xml.xml -> t
> end
>
> module MessageSender (C : CONSTRUCTOR) =
> struct
> let send msg = print_string (Xml.to_string (C.as_xml msg))
> end
>
> let _ =
> let module M = MessageSender(Header) in
> M.send (Header.make "Header" "TestMessage" "DEV")
>
>--
>Andreas Rossberg, rossberg@ps.uni-sb.de
>
>Let's get rid of those possible thingies! -- TB
>
-------------------
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
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2004-03-15 16:20 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-03-14 19:05 [Caml-list] Module/functor question ronniec95
2004-03-14 19:22 ` Yamagata Yoriyuki
2004-03-14 23:46 ` ronniec95
2004-03-15 12:34 ` Andreas Rossberg
2004-03-15 16:20 ` ronniec95
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox