caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Creating a Map from custom type
@ 2013-11-14 10:39 Ollie Frolovs
  2013-11-14 10:56 ` David Allsopp
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Ollie Frolovs @ 2013-11-14 10:39 UTC (permalink / raw)
  To: caml users

Hello, list!

I’m learning how to use Maps in OCaml and after having read the relevant chapter in Real World Ocaml i still do not understand what i need to do to solve my problem –

I defined a datatype in subroutes.mli:

open Core.Std

(** A data structure to store solved subproblems for 
    dynamic programming (Bellman 1961) approach to solving TSP *)
type t

(** The empty data structure *)
val empty : t

(** Store a solution to a subproblem *)
val add : t -> (int list * int) -> (int * int list) -> t

(** Find a solution to a subproblem *)
val find : t -> (int list * int) -> (int * int list) option

(** Convert the data structure to an association list.
    Useful for printing but much too slow for anything else *)
val to_list : t -> ((int list * int) * (int * int list)) list

My current implementation uses associative lists, in subroute.ml:

open Core.Std
type t = ((int list * int) * (int * int list)) list
let empty = []
let to_list x = x
let add t k v = List.Assoc.add t k v
let find t k = List.Assoc.find t k

I would like to use a Map instead. The key for my Map must have the type (int list * int) and the values have the type (int * int list). If i understood it correctly, because the key is a tuple and not one of the built-in simple data types (string, int, etc), because of this i have to provide a custom comparator. This is first thing that i am not sure of.

Assuming that i do need to provide a comparator, what i don’t understand is this –

On page 272 of RWO they create a comparator for a string to int Map as following:

module Reverse = Comparator.Make(struct
  type t = string
  let sexp_of_t = String.sexp_of_t
  let t_of_sexp = String.t_of_sexp
  let compare x y = String.compare y x
end);;

What is the type t – is it the type of the key only? Would, in my case it be type t = (int list * int) ?
Is there an easy way to have sexp part auto-generated/ignored? They discuss “with sexp” on later pages but it uses functors (which i am not yet familiar with) and i found that example very confusing.

Also, i do not understand the purpose of the comparison function. I just store different subroutes, there really isn’t anything i would “compare” them with/for. I understand the compare function is necessary for the Map to be able to find things, but how do i define it for my type in the most painless way?

I guess what i want, ideally, is like a hash from Python where i could just stuff a key and value into and not worry about the implementation. I understand that OCaml is strongly typed, so it cannot be that simple but as of now i don’t know what to do to have this problem solved. I googled for explanations but did not find anything useful yet. 

Please help?!

— Ollie


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

* RE: [Caml-list] Creating a Map from custom type
  2013-11-14 10:39 [Caml-list] Creating a Map from custom type Ollie Frolovs
@ 2013-11-14 10:56 ` David Allsopp
  2013-11-14 11:02 ` Malcolm Matalka
  2013-11-14 11:21 ` Mark Shinwell
  2 siblings, 0 replies; 7+ messages in thread
From: David Allsopp @ 2013-11-14 10:56 UTC (permalink / raw)
  To: caml users

Ollie Frolovs wrote:
> I'm learning how to use Maps in OCaml and after having read the relevant
> chapter in Real World Ocaml i still do not understand what i need to do to
> solve my problem -
> 
> I defined a datatype in subroutes.mli:
> 
> open Core.Std
> 
> (** A data structure to store solved subproblems for
>     dynamic programming (Bellman 1961) approach to solving TSP *)
> type t
> 
> (** The empty data structure *)
> val empty : t
> 
> (** Store a solution to a subproblem *)
> val add : t -> (int list * int) -> (int * int list) -> t
> 
> (** Find a solution to a subproblem *)
> val find : t -> (int list * int) -> (int * int list) option
> 
> (** Convert the data structure to an association list.
>     Useful for printing but much too slow for anything else *)
> val to_list : t -> ((int list * int) * (int * int list)) list
> 
> My current implementation uses associative lists, in subroute.ml:
> 
> open Core.Std
> type t = ((int list * int) * (int * int list)) list
> let empty = []
> let to_list x = x
> let add t k v = List.Assoc.add t k v
> let find t k = List.Assoc.find t k
> 
> I would like to use a Map instead. The key for my Map must have the type
> (int list * int) and the values have the type (int * int list). If i
> understood it correctly, because the key is a tuple and not one of the
> built-in simple data types (string, int, etc), because of this i have to
> provide a custom comparator. This is first thing that i am not sure of.
> 
> Assuming that i do need to provide a comparator, what i don't understand
> is this -
> 
> On page 272 of RWO they create a comparator for a string to int Map as
> following:
> 
> module Reverse = Comparator.Make(struct
>   type t = string
>   let sexp_of_t = String.sexp_of_t
>   let t_of_sexp = String.t_of_sexp
>   let compare x y = String.compare y x
> end);;
>
> What is the type t - is it the type of the key only? Would, in my case it
> be type t = (int list * int) ?

Yes.

> Is there an easy way to have sexp part auto-generated/ignored? They
> discuss "with sexp" on later pages but it uses functors (which i am not
> yet familiar with) and i found that example very confusing.

Erm, at the risk of a politically-incorrect opinion, you'd be having a simpler time using the Standard Library, rather than Core! However, that maybe because you have to accept needing to read more of RWO first...

> Also, i do not understand the purpose of the comparison function. I just
> store different subroutes, there really isn't anything i would "compare"
> them with/for. I understand the compare function is necessary for the Map
> to be able to find things, but how do i define it for my type in the most
> painless way?

Yes - your data type is simply tuples, so the standard polymorphic compare will work. Using StdLib's Map, it's quite normal to have:

module MyMap = Map.Make(struct type t = (int list * int) let compare = compare end);;

(I would sometimes choose to write let compare = Pervasives.compare as let compare = compare can read oddly)

> I guess what i want, ideally, is like a hash from Python where i could
> just stuff a key and value into and not worry about the implementation. I
> understand that OCaml is strongly typed, so it cannot be that simple but
> as of now i don't know what to do to have this problem solved. I googled
> for explanations but did not find anything useful yet.

There's an example at http://caml.inria.fr/pub/docs/oreilly-book/html/book-ora132.html#toc187 (note that that example defines its compare function in detail, but that's because its choosing to care about the ordering - using Pervasives.compare is more appropriate in your case where you don't care what the ordering is, you simply need one!)

HTH,


David 

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

* Re: [Caml-list] Creating a Map from custom type
  2013-11-14 10:39 [Caml-list] Creating a Map from custom type Ollie Frolovs
  2013-11-14 10:56 ` David Allsopp
@ 2013-11-14 11:02 ` Malcolm Matalka
  2013-11-14 11:21 ` Mark Shinwell
  2 siblings, 0 replies; 7+ messages in thread
From: Malcolm Matalka @ 2013-11-14 11:02 UTC (permalink / raw)
  To: Ollie Frolovs; +Cc: caml users

Hello!

Here is an example of a module where I creates and uses a map where the
key is two tuples.

https://github.com/orbitz/ocaml-pastry/blob/master/lib/pastry/routing_table.ml#L3

Ollie Frolovs <of12343@my.bristol.ac.uk> writes:

> Hello, list!
>
> I’m learning how to use Maps in OCaml and after having read the relevant chapter in Real World Ocaml i still do not understand what i need to do to solve my problem –
>
> I defined a datatype in subroutes.mli:
>
> open Core.Std
>
> (** A data structure to store solved subproblems for 
>     dynamic programming (Bellman 1961) approach to solving TSP *)
> type t
>
> (** The empty data structure *)
> val empty : t
>
> (** Store a solution to a subproblem *)
> val add : t -> (int list * int) -> (int * int list) -> t
>
> (** Find a solution to a subproblem *)
> val find : t -> (int list * int) -> (int * int list) option
>
> (** Convert the data structure to an association list.
>     Useful for printing but much too slow for anything else *)
> val to_list : t -> ((int list * int) * (int * int list)) list
>
> My current implementation uses associative lists, in subroute.ml:
>
> open Core.Std
> type t = ((int list * int) * (int * int list)) list
> let empty = []
> let to_list x = x
> let add t k v = List.Assoc.add t k v
> let find t k = List.Assoc.find t k
>
> I would like to use a Map instead. The key for my Map must have the type (int list * int) and the values have the type (int * int list). If i understood it correctly, because the key is a tuple and not one of the built-in simple data types (string, int, etc), because of this i have to provide a custom comparator. This is first thing that i am not sure of.
>
> Assuming that i do need to provide a comparator, what i don’t understand is this –
>
> On page 272 of RWO they create a comparator for a string to int Map as following:
>
> module Reverse = Comparator.Make(struct
>   type t = string
>   let sexp_of_t = String.sexp_of_t
>   let t_of_sexp = String.t_of_sexp
>   let compare x y = String.compare y x
> end);;
>
> What is the type t – is it the type of the key only? Would, in my case it be type t = (int list * int) ?
> Is there an easy way to have sexp part auto-generated/ignored? They discuss “with sexp” on later pages but it uses functors (which i am not yet familiar with) and i found that example very confusing.
>
> Also, i do not understand the purpose of the comparison function. I just store different subroutes, there really isn’t anything i would “compare” them with/for. I understand the compare function is necessary for the Map to be able to find things, but how do i define it for my type in the most painless way?
>
> I guess what i want, ideally, is like a hash from Python where i could just stuff a key and value into and not worry about the implementation. I understand that OCaml is strongly typed, so it cannot be that simple but as of now i don’t know what to do to have this problem solved. I googled for explanations but did not find anything useful yet. 
>
> Please help?!
>
> — Ollie

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

* Re: [Caml-list] Creating a Map from custom type
  2013-11-14 10:39 [Caml-list] Creating a Map from custom type Ollie Frolovs
  2013-11-14 10:56 ` David Allsopp
  2013-11-14 11:02 ` Malcolm Matalka
@ 2013-11-14 11:21 ` Mark Shinwell
  2013-11-14 12:03   ` Yaron Minsky
  2 siblings, 1 reply; 7+ messages in thread
From: Mark Shinwell @ 2013-11-14 11:21 UTC (permalink / raw)
  To: Ollie Frolovs; +Cc: caml users

On 14 November 2013 10:39, Ollie Frolovs <of12343@my.bristol.ac.uk> wrote:
> My current implementation uses associative lists, in subroute.ml:
>
> open Core.Std
> type t = ((int list * int) * (int * int list)) list
> let empty = []
> let to_list x = x
> let add t k v = List.Assoc.add t k v
> let find t k = List.Assoc.find t k
>
> I would like to use a Map instead. The key for my Map must have the type (int list * int) and the values have the type (int * int list). If i understood it correctly, because the key is a tuple and not one of the built-in simple data types (string, int, etc), because of this i have to provide a custom comparator. This is first thing that i am not sure of.

I think you need something like:

module Key = struct
  type t = int list * int with sexp, compare
end

module My_map = Map.Make (Key)

Then, for example:

  let map =
    My_map.add My_map.empty
      ~key:([42], 0)
      ~data:(1, [2])

The "with compare" auto-generates a "compare" function for
you.  Using explicit comparison functions, as Core strongly
encourages, does unfortunately mean a bit more code at times
but is arguably vastly more sustainable as your codebase
grows.  In such scenarios it becomes increasingly unlikely
that the correct notion of comparison on one of your many
abstract types coincides with the structural comparison
on whatever implementation those types happen to have today.

Mark

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

* Re: [Caml-list] Creating a Map from custom type
  2013-11-14 11:21 ` Mark Shinwell
@ 2013-11-14 12:03   ` Yaron Minsky
  2013-11-14 12:11     ` David House
  0 siblings, 1 reply; 7+ messages in thread
From: Yaron Minsky @ 2013-11-14 12:03 UTC (permalink / raw)
  To: Mark Shinwell; +Cc: Ollie Frolovs, caml users

It's worth noting that if you want a simply polymorphic map, you can
have one, you just need to be explicit about what you're doing:

utop # let map = Map.Poly.of_alist_exn [1, "one"; 2, "two"; 3, "three"];;
val map : (int, string) Map.Poly.t = <abstr>

which is probably the lowest-pain approach.  Polymorphic compare
(which is what this is based on) has some downside, but is perfectly
good for many use-cases.  RWO covers in detail the pitfalls of
polymorphic compare, but it doesn't mean you should avoid it,
especially when you're getting started.

As for David's point about Core vs the stdlib, I think creating a map
with a polymorphic comparison function is actually quite a bit easier
in Core than it is with the stdlib, since no functor application is
required.

y

On Thu, Nov 14, 2013 at 6:21 AM, Mark Shinwell <mshinwell@janestreet.com> wrote:
> On 14 November 2013 10:39, Ollie Frolovs <of12343@my.bristol.ac.uk> wrote:
>> My current implementation uses associative lists, in subroute.ml:
>>
>> open Core.Std
>> type t = ((int list * int) * (int * int list)) list
>> let empty = []
>> let to_list x = x
>> let add t k v = List.Assoc.add t k v
>> let find t k = List.Assoc.find t k
>>
>> I would like to use a Map instead. The key for my Map must have the type (int list * int) and the values have the type (int * int list). If i understood it correctly, because the key is a tuple and not one of the built-in simple data types (string, int, etc), because of this i have to provide a custom comparator. This is first thing that i am not sure of.
>
> I think you need something like:
>
> module Key = struct
>   type t = int list * int with sexp, compare
> end
>
> module My_map = Map.Make (Key)
>
> Then, for example:
>
>   let map =
>     My_map.add My_map.empty
>       ~key:([42], 0)
>       ~data:(1, [2])
>
> The "with compare" auto-generates a "compare" function for
> you.  Using explicit comparison functions, as Core strongly
> encourages, does unfortunately mean a bit more code at times
> but is arguably vastly more sustainable as your codebase
> grows.  In such scenarios it becomes increasingly unlikely
> that the correct notion of comparison on one of your many
> abstract types coincides with the structural comparison
> on whatever implementation those types happen to have today.
>
> Mark
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

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

* Re: [Caml-list] Creating a Map from custom type
  2013-11-14 12:03   ` Yaron Minsky
@ 2013-11-14 12:11     ` David House
  2013-11-15  9:36       ` Ollie Frolovs
  0 siblings, 1 reply; 7+ messages in thread
From: David House @ 2013-11-14 12:11 UTC (permalink / raw)
  To: Yaron Minsky; +Cc: Mark Shinwell, Ollie Frolovs, caml users

To follow up on Mark's example, you can use the following slightly
more general idiom:

module My_thing = struct
  module T = struct
    type t = int * string * string with sexp, compare
  end
  include T
  include Comparable.Make(T)

  let do_some_stuff t = ...
end

Then My_thing will satisfy the Comparable signature, which means
you'll have My_thing.Map, as well as My_thing.Set, My_thing.equal,
My_thing.(<) etc.

We do this on basically every type in core, since you'll want to use
everything in a set sooner or later :)

The "gold standard" for such types is the Identifiable signature. This
is basically the union of the Comparable signature, the Hashable
signature (which gives you hashtables, hash-sets etc.) and the
Stringable signature (to/from strings). You can get there with just a
little more work:

module My_thing = struct
  module T = struct
    type t = ... with sexp, compare, bin_io
    let hash = Hashtbl.hash
    let to_string t = ...
    let of_string t = ...
    let module_name = "My_lib.My_thing" (* for the toplevel *)
  end
  include T
  include Identifiable.Make(T)

  (* other functions here *)
end

If you want the string representation to be the same as the sexp
representation, that's possible too with only a little more
clunkiness:

module My_thing = struct
  module T = struct
    module T' = struct
      type t = ... with sexp, compare, bin_io
    end
    include T'
    include Sexpable.To_stringable(T')
    let hash = Hashtbl.hash
    let module_name = "My_lib.My_thing" (* for the toplevel *)
  end
  include T
  include Identifiable.Make(T)

 (* other functions here *)
end

On 14 November 2013 12:03, Yaron Minsky <yminsky@janestreet.com> wrote:
> It's worth noting that if you want a simply polymorphic map, you can
> have one, you just need to be explicit about what you're doing:
>
> utop # let map = Map.Poly.of_alist_exn [1, "one"; 2, "two"; 3, "three"];;
> val map : (int, string) Map.Poly.t = <abstr>
>
> which is probably the lowest-pain approach.  Polymorphic compare
> (which is what this is based on) has some downside, but is perfectly
> good for many use-cases.  RWO covers in detail the pitfalls of
> polymorphic compare, but it doesn't mean you should avoid it,
> especially when you're getting started.
>
> As for David's point about Core vs the stdlib, I think creating a map
> with a polymorphic comparison function is actually quite a bit easier
> in Core than it is with the stdlib, since no functor application is
> required.
>
> y
>
> On Thu, Nov 14, 2013 at 6:21 AM, Mark Shinwell <mshinwell@janestreet.com> wrote:
>> On 14 November 2013 10:39, Ollie Frolovs <of12343@my.bristol.ac.uk> wrote:
>>> My current implementation uses associative lists, in subroute.ml:
>>>
>>> open Core.Std
>>> type t = ((int list * int) * (int * int list)) list
>>> let empty = []
>>> let to_list x = x
>>> let add t k v = List.Assoc.add t k v
>>> let find t k = List.Assoc.find t k
>>>
>>> I would like to use a Map instead. The key for my Map must have the type (int list * int) and the values have the type (int * int list). If i understood it correctly, because the key is a tuple and not one of the built-in simple data types (string, int, etc), because of this i have to provide a custom comparator. This is first thing that i am not sure of.
>>
>> I think you need something like:
>>
>> module Key = struct
>>   type t = int list * int with sexp, compare
>> end
>>
>> module My_map = Map.Make (Key)
>>
>> Then, for example:
>>
>>   let map =
>>     My_map.add My_map.empty
>>       ~key:([42], 0)
>>       ~data:(1, [2])
>>
>> The "with compare" auto-generates a "compare" function for
>> you.  Using explicit comparison functions, as Core strongly
>> encourages, does unfortunately mean a bit more code at times
>> but is arguably vastly more sustainable as your codebase
>> grows.  In such scenarios it becomes increasingly unlikely
>> that the correct notion of comparison on one of your many
>> abstract types coincides with the structural comparison
>> on whatever implementation those types happen to have today.
>>
>> Mark
>>
>> --
>> Caml-list mailing list.  Subscription management and archives:
>> https://sympa.inria.fr/sympa/arc/caml-list
>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

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

* Re: [Caml-list] Creating a Map from custom type
  2013-11-14 12:11     ` David House
@ 2013-11-15  9:36       ` Ollie Frolovs
  0 siblings, 0 replies; 7+ messages in thread
From: Ollie Frolovs @ 2013-11-15  9:36 UTC (permalink / raw)
  To: caml users; +Cc: David House, Yaron Minsky, Mark Shinwell, Malcolm Matalka

Thank you David, Yaron, Mark & Malcolm! 

I managed to replace the associative list with a map and now my OCaml implementation of "Dynamic Programming Treatment of the Travelling Salesman Problem” (Bellman, 1961) can easily handle N=20 which is more than enough for my project since i'm using clustering techniques to split the graph into subgraphs. I also learned a lot about modules, interfaces, maps and even the basics of functors. So much to learn still! 

Thanks again.

— Ollie

On 14 Nov 2013, at 12:11, David House <dhouse@janestreet.com> wrote:

> To follow up on Mark's example, you can use the following slightly
> more general idiom:
> 
> module My_thing = struct
>  module T = struct
>    type t = int * string * string with sexp, compare
>  end
>  include T
>  include Comparable.Make(T)
> 
>  let do_some_stuff t = ...
> end
> 
> Then My_thing will satisfy the Comparable signature, which means
> you'll have My_thing.Map, as well as My_thing.Set, My_thing.equal,
> My_thing.(<) etc.
> 
> We do this on basically every type in core, since you'll want to use
> everything in a set sooner or later :)
> 
> The "gold standard" for such types is the Identifiable signature. This
> is basically the union of the Comparable signature, the Hashable
> signature (which gives you hashtables, hash-sets etc.) and the
> Stringable signature (to/from strings). You can get there with just a
> little more work:
> 
> module My_thing = struct
>  module T = struct
>    type t = ... with sexp, compare, bin_io
>    let hash = Hashtbl.hash
>    let to_string t = ...
>    let of_string t = ...
>    let module_name = "My_lib.My_thing" (* for the toplevel *)
>  end
>  include T
>  include Identifiable.Make(T)
> 
>  (* other functions here *)
> end
> 
> If you want the string representation to be the same as the sexp
> representation, that's possible too with only a little more
> clunkiness:
> 
> module My_thing = struct
>  module T = struct
>    module T' = struct
>      type t = ... with sexp, compare, bin_io
>    end
>    include T'
>    include Sexpable.To_stringable(T')
>    let hash = Hashtbl.hash
>    let module_name = "My_lib.My_thing" (* for the toplevel *)
>  end
>  include T
>  include Identifiable.Make(T)
> 
> (* other functions here *)
> end
> 
> On 14 November 2013 12:03, Yaron Minsky <yminsky@janestreet.com> wrote:
>> It's worth noting that if you want a simply polymorphic map, you can
>> have one, you just need to be explicit about what you're doing:
>> 
>> utop # let map = Map.Poly.of_alist_exn [1, "one"; 2, "two"; 3, "three"];;
>> val map : (int, string) Map.Poly.t = <abstr>
>> 
>> which is probably the lowest-pain approach.  Polymorphic compare
>> (which is what this is based on) has some downside, but is perfectly
>> good for many use-cases.  RWO covers in detail the pitfalls of
>> polymorphic compare, but it doesn't mean you should avoid it,
>> especially when you're getting started.
>> 
>> As for David's point about Core vs the stdlib, I think creating a map
>> with a polymorphic comparison function is actually quite a bit easier
>> in Core than it is with the stdlib, since no functor application is
>> required.
>> 
>> y
>> 
>> On Thu, Nov 14, 2013 at 6:21 AM, Mark Shinwell <mshinwell@janestreet.com> wrote:
>>> On 14 November 2013 10:39, Ollie Frolovs <of12343@my.bristol.ac.uk> wrote:
>>>> My current implementation uses associative lists, in subroute.ml:
>>>> 
>>>> open Core.Std
>>>> type t = ((int list * int) * (int * int list)) list
>>>> let empty = []
>>>> let to_list x = x
>>>> let add t k v = List.Assoc.add t k v
>>>> let find t k = List.Assoc.find t k
>>>> 
>>>> I would like to use a Map instead. The key for my Map must have the type (int list * int) and the values have the type (int * int list). If i understood it correctly, because the key is a tuple and not one of the built-in simple data types (string, int, etc), because of this i have to provide a custom comparator. This is first thing that i am not sure of.
>>> 
>>> I think you need something like:
>>> 
>>> module Key = struct
>>>  type t = int list * int with sexp, compare
>>> end
>>> 
>>> module My_map = Map.Make (Key)
>>> 
>>> Then, for example:
>>> 
>>>  let map =
>>>    My_map.add My_map.empty
>>>      ~key:([42], 0)
>>>      ~data:(1, [2])
>>> 
>>> The "with compare" auto-generates a "compare" function for
>>> you.  Using explicit comparison functions, as Core strongly
>>> encourages, does unfortunately mean a bit more code at times
>>> but is arguably vastly more sustainable as your codebase
>>> grows.  In such scenarios it becomes increasingly unlikely
>>> that the correct notion of comparison on one of your many
>>> abstract types coincides with the structural comparison
>>> on whatever implementation those types happen to have today.
>>> 
>>> Mark
>>> 
>>> --
>>> Caml-list mailing list.  Subscription management and archives:
>>> https://sympa.inria.fr/sympa/arc/caml-list
>>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>> 
>> --
>> Caml-list mailing list.  Subscription management and archives:
>> https://sympa.inria.fr/sympa/arc/caml-list
>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>> Bug reports: http://caml.inria.fr/bin/caml-bugs


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

end of thread, other threads:[~2013-11-15  9:36 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-11-14 10:39 [Caml-list] Creating a Map from custom type Ollie Frolovs
2013-11-14 10:56 ` David Allsopp
2013-11-14 11:02 ` Malcolm Matalka
2013-11-14 11:21 ` Mark Shinwell
2013-11-14 12:03   ` Yaron Minsky
2013-11-14 12:11     ` David House
2013-11-15  9:36       ` Ollie Frolovs

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