caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Gabriel Scherer <gabriel.scherer@gmail.com>
To: Hakan Suka <hakan40us@yahoo.com>
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] functor inside a class
Date: Mon, 23 May 2011 23:58:07 +0200	[thread overview]
Message-ID: <BANLkTinJkv98aek_oAd5DrzPKf5h6FFrHQ@mail.gmail.com> (raw)
In-Reply-To: <172756.45853.qm@web120203.mail.ne1.yahoo.com>

[-- Attachment #1: Type: text/plain, Size: 3583 bytes --]

Local modules only make sense when they are used locally. You cannot return
a value whose type depends on the local module (what woud that mean?). So in
your example, LabelSet should not be a local module, as it is used in the
return type of the "get" method.

For a simpler example of this problem:

> # let f x =
>  let module M = Map.Make(struct type t = int let compare = compare end) in
>  M.singleton 1 x;;
> Error: This `let module' expression has type 'a M.t
> In this type, the locally bound module name M escapes its scope
>

If you need to use a set, you must request an ordering on your labels. The
type-safe way to do this in OCaml is to use modules, so you should define
your class in a functor, rather than as a parametrized class.

# module Tracker (Label : Set.OrderedType) = struct
>     module LabelSet = Set.Make(Label)
>     class tracker size = object
>       method get (_ : int) = LabelSet.empty
>     end
>   end;;
>

You could consider this an issue with ordering-parametrized functors: they
require code using them to get functorized as well, which may in turn
require more important changes in your application. But starting from 3.12
it's easier to contain functorization locally, and I think this design is
viable. The other possibility is to use a polymorphic datatype that relies
on the apparently polymorphic comparison function, but this is less
type-safe: you cannot use your own comparison function, so you won't be able
to use labels containing cycles or closures, and you may mistakenly mix
result sets from different trackers.

On Mon, May 23, 2011 at 1:17 PM, Hakan Suka <hakan40us@yahoo.com> wrote:
> Hi everyone,
>
> I tried the ocaml-beginners list with this question but did not get a good
> solution, so I am retrying here.
>
> I want to create a parameterised class that takes as input a polymorphic
"label"
>
> type and internally stores information using a Set of that type. However,
I
> cannot get the functor to work inside a class, so I wonder whether this is
> possible.
>
> For example, the following works:
>
> module LabelSet =
> Set.Make (struct type t = int let compare = compare end)
>
> class ['a] tracker size =
> object
>
> val nums_to_track_tbl : (int32, LabelSet.t) Hashtbl.t =
> Hashtbl.create size
>
> method get pos = Hashtbl.find_all nums_to_track_tbl pos
> end
>
> But can I have a local module definition so that the I can have a tracker
not
> only for integers, but for any type being passed as input? The following
does
> not work:
>
> class ['a] tracker size =
> let module LabelSet =
> Set.Make (struct type t = 'a let compare = compare end)
> in
> object
> val nums_to_track_tbl : (int32, LabelSet.t) Hashtbl.t =
> Hashtbl.create size
>
> method get pos = Hashtbl.find_all nums_to_track_tbl pos
>
> end
>
> If this is not possible, would it work in Ocaml 3.12 with first-class
modules?
>
> I have seen the following code in the manual which seems fairly close of
what I
> would need inside the parametrised class, but not sure if I can use the
output
> of make_set inside the module. I haven't tested this because I have Ocaml
3.11.2
>
> let make_set (type s) cmp =
> let module S = Set.Make(struct
> type t = s
> let compare = cmp
> end) in
> (module S : Set.S with type elt = s)
>
> If that does not work, any suggestions on how to implement this?
>
> Thanks,
> Hakan
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
>

[-- Attachment #2: Type: text/html, Size: 4645 bytes --]

      parent reply	other threads:[~2011-05-23 21:58 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-23 11:17 Hakan Suka
2011-05-23 19:34 ` Guillaume Yziquel
2011-05-23 19:44   ` Ashish Agarwal
2011-05-23 21:58 ` Gabriel Scherer [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=BANLkTinJkv98aek_oAd5DrzPKf5h6FFrHQ@mail.gmail.com \
    --to=gabriel.scherer@gmail.com \
    --cc=caml-list@inria.fr \
    --cc=hakan40us@yahoo.com \
    /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).