From: Dawid Toton <d...@wp.pl> > 1. The following piece of code contains illegal constructs. These are > functor applications marked with (* ? *). > Basically, I need module type of what is produced by functor. > My first question is: what is the proper, "canonical" workaround for > unavailability of applications marked (* ? *) ? > > module type Big = sig type t type u end > module type Small = sig type t end > > module type MakeEdge = functor (Big : Big) -> sig val foo : Big.t > option end > module MakeEdge = functor (Big : Big) -> struct let foo = None end > > module type Add_boilerplate = functor (Small:Small) -> sig type t end > module Add_boilerplate = functor (Small:Small) -> struct type t = > Small.t type u = t end > > module type ConvenientEdge = functor (Small:Small) -> MakeEdge > (Add_boilerplate (Small)) (* ? *) > module ConvenientEdge = functor (Small:Small) -> MakeEdge > (Add_boilerplate (Small)) > > module SmallX = struct type t = int end > module EdgeX = ConvenientEdge (SmallX) > module type EdgeX = ConvenientEdge (SmallX) (* ? *) > > module Algorithm = functor (EdgeX : EdgeX) -> struct let doit = > EdgeX.foo end > > 2. And the related question: why one can't do functor applications in > module types as in above lines marked with (* ? *) ? Is there some > theoretical reason?
You are mixing two things: the signature of a functor (which cannot be applied to anything, since it is a signature, not a functor), and a functor returning a signature. Using ocaml 3.11, you have to wrap the returned signature inside a structure: (* Signature wrapped inside a structure *) module MakeEdgeSig (Big : Big) = struct module type S = sig val foo : Big.t option end end module MakeEdge (Big : Big) = struct let foo = None end module Add_boilerplate (Small:Small) = struct type t = Small.t type u = t end module ConvenientEdgeSig (Small:Small) = MakeEdgeSig (Add_boilerplate (Small)) module ConvenientEdge (Small:Small) = MakeEdge (Add_boilerplate (Small)) module SmallX = struct type t = int end module EdgeX = ConvenientEdge (SmallX) (* Build the corresponding signature *) module type EdgeX = ConvenientEdgeSig(SmallX).S module Algorithm (EdgeX : EdgeX) = struct let doit = EdgeX.foo end > 3. Will the "module type of..." feature of 3.12 help with this? I can > imagine e.g.: > > module type EdgeX = (module type of (ConvenientEdge (SmallX))) Indeed, if your only goal is to obtain this specific signature, this does the trick. But if you want to specify signatures independently of implementations, you can also use the new destructive substitution mechanism. (* Requires ocaml 3.12 *) (* New signature Edge, parameterized with t *) module type Edge = sig type t val foo : t option end (* Edge with type t := Big.t == sig val foo : Big.t option end *) module MakeEdge (Big : Big) : Edge with type t := Big.t = struct let foo = None end module Add_boilerplate (Small:Small) = struct type t = Small.t type u = t end module ConvenientEdge (Small:Small) : Edge with type t := Small.t = MakeEdge(Add_boilerplate (Small)) module SmallX = struct type t = int end module EdgeX = ConvenientEdge (SmallX) (* Build the result signature by instantiating Edge signature *) module type EdgeX = Edge with type t := SmallX.t (* Alternative approach, obtain the same signature from EdgeX itself *) module type EdgeX' = module type of EdgeX module Algorithm(EdgeX : EdgeX) = struct let doit = EdgeX.foo end Hope this helps, Jacques Garrigue _______________________________________________ Caml-list mailing list. Subscription management: http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list Archives: http://caml.inria.fr Beginner's list: http://groups.yahoo.com/group/ocaml_beginners Bug reports: http://caml.inria.fr/bin/caml-bugs