caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] functor inside a class
@ 2011-05-23 11:17 Hakan Suka
  2011-05-23 19:34 ` Guillaume Yziquel
  2011-05-23 21:58 ` Gabriel Scherer
  0 siblings, 2 replies; 4+ messages in thread
From: Hakan Suka @ 2011-05-23 11:17 UTC (permalink / raw)
  To: caml-list

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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] functor inside a class
  2011-05-23 11:17 [Caml-list] functor inside a class Hakan Suka
@ 2011-05-23 19:34 ` Guillaume Yziquel
  2011-05-23 19:44   ` Ashish Agarwal
  2011-05-23 21:58 ` Gabriel Scherer
  1 sibling, 1 reply; 4+ messages in thread
From: Guillaume Yziquel @ 2011-05-23 19:34 UTC (permalink / raw)
  To: Hakan Suka; +Cc: caml-list

Le Monday 23 May 2011 à 04:17:00 (-0700), Hakan Suka a écrit :
> Hi everyone,
> 
> 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

First of all, the scope in which you can refer to LabelSet is local to
the class declaration. However, the class method get has a type which
refers to LabelSet. That's out of scope.

More importantly, it seems that

	let f x = let module M = struct end in x

is syntactically valid, while it doesn't seem to work out the same way for
class declarations:

	class ['a] tracker = fun size -> let module M = struct end in object end

gives a syntax error.

You should create your local module somewhere else than before 'object'
'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?

The big point is that you need the 'get' method to return something which
is a 't' element of a module satisfying the 'Set.S with type t = 'a'
signature.

You need a type constructor for that. Set.Make(String).t is a valid
type, but I do not see how parametrise String for some other 'a type.

The following works:

	type 'a set_module = (module Set.S with type elt = 'a)

	let make_set (type s) ?(cmp = compare) () =
		let module S = Set.Make (struct type t = s let compare = cmp end) in
		(module S : Set.S with type elt = s)

	class ['a] tracker size = object
		val set = make_set ()   
		val nums_to_track_tbl : (int32, 'a set_module) Hashtbl.t = Hashtbl.create size
		method get pos = Hashtbl.find_all nums_to_track_tbl pos
	end

But it's a 'a set_module, not a 'a set, so first-class modules do not
seem so useful at first glance...

What you'd need is not a

	type 'a set_module = (module Set.S with type elt = 'a)

but something like

	type 'a set = (module Set.S with type elt = 'a).t

(which is not valid), and to my knowledge, this cannot be done.

However, I think there is a polymorphic-not-functorised code for maps
and sets lying out somewhere on the net. This is likely your best bet.

> Thanks,
> Hakan

-- 
     Guillaume Yziquel


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] functor inside a class
  2011-05-23 19:34 ` Guillaume Yziquel
@ 2011-05-23 19:44   ` Ashish Agarwal
  0 siblings, 0 replies; 4+ messages in thread
From: Ashish Agarwal @ 2011-05-23 19:44 UTC (permalink / raw)
  To: Guillaume Yziquel; +Cc: Hakan Suka, caml-list

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

On Mon, May 23, 2011 at 3:34 PM, Guillaume Yziquel <
guillaume.yziquel@citycable.ch> wrote:


>  However, I think there is a polymorphic-not-functorised code for maps
> and sets lying out somewhere on the net. This is likely your best bet.
>

These are available in Batteries as PMap and PSet.

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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] functor inside a class
  2011-05-23 11:17 [Caml-list] functor inside a class Hakan Suka
  2011-05-23 19:34 ` Guillaume Yziquel
@ 2011-05-23 21:58 ` Gabriel Scherer
  1 sibling, 0 replies; 4+ messages in thread
From: Gabriel Scherer @ 2011-05-23 21:58 UTC (permalink / raw)
  To: Hakan Suka; +Cc: caml-list

[-- 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 --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-05-23 21:58 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-23 11:17 [Caml-list] functor inside a class Hakan Suka
2011-05-23 19:34 ` Guillaume Yziquel
2011-05-23 19:44   ` Ashish Agarwal
2011-05-23 21:58 ` Gabriel Scherer

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).