caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
To: d0@wp.pl
Cc: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] Module type of a structure returned by functor
Date: Tue, 27 Apr 2010 09:23:19 +0900 (JST)	[thread overview]
Message-ID: <20100427.092319.160739744.garrigue@math.nagoya-u.ac.jp> (raw)
In-Reply-To: <4BD229E4.4050003@wp.pl>

From: Dawid Toton <d0@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


      parent reply	other threads:[~2010-04-27  0:23 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-04-23 23:14 Dawid Toton
2010-04-26 16:33 ` Dawid Toton
2010-04-26 16:48   ` [Caml-list] " Vincent Aravantinos
2010-04-26 16:54   ` rossberg
2010-04-27  0:23 ` Jacques Garrigue [this message]

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=20100427.092319.160739744.garrigue@math.nagoya-u.ac.jp \
    --to=garrigue@math.nagoya-u.ac.jp \
    --cc=caml-list@yquem.inria.fr \
    --cc=d0@wp.pl \
    /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).