How to specialize `Core.Map` to a `Map (K) (V)` functor?


I understand that a Core.Map is polymorphic over the value type:

# module S = Map.Make (String) ;;
# let s_int = S.add_exn S.empty ~key:"0" ~data:0 ;;
# let s_str = S.add_exn S.empty ~key:"0" ~data:"zero" ;;

However, I want to create specialized modules for each K -> V map type, something like:

# module SI = MyMap (String) (Int) ;;
# let si = SI.add_exn SI.empty ~key:"0" ~data:0 ;;
# let si' = SI.add_exn SI.empty ~key:"0" ~data:"zero" ;; (* compiler error *)
# module SS = MyMap (String) (String) ;;
# let ss = SS.add_exn SS.empty ~key:"0" ~data:"zero" ;;
# let ss' = SS.add_exn SS.empty ~key:"0" ~data:0 ;; (* compiler error *)

Is it possible to extend Map.Make (String) to MyMap and specialize its functions like this?


Do you need to have it be the whole module?

module StringMap = Map.Make (String)

type si = int StringMap.t

Also, I don’t think Map.Make is part of Core.Map. Are you thinking of the standard library Map?

Thanks @bcc32.

The type si solution is what I am using of now, but I was wondering if there is anyway of having the whole module. To get the compile-time errors that I mentioned in my original post, one would have to do something like:

# module S = MyMap (String) ;;
# type t_si = int S.t ;;
# let si : t_si = S.add_exn S.empty ~key:"0" ~data:0 ;;
# let si' : t_si = S.add_exn S.empty ~key:"0" ~data:"zero" ;; (* compiler error *)

Notice the explicit type annotations, without which there would be no compiler error since empty itself is polymorphic.

Core_kernel does have a Map.Make functor.

Ah, I was looking in the wrong place.

No, there is no way to fix the data type, short of defining a signature like so:

module type Map_with_fixed_data = sig
  val filter_map : t -> f:('a -> 'a option) -> t

where you basically fix each type yourself. I still don’t see why you’d really want this, though. The compiler will warn you if you try to use a map with the wrong data type later on, no? Can you provide a concrete use-case?

You are correct. When I use the actual Map.t values with the wrong type, I would get a compilation error. This was purely out of curiosity.

Thinking more about it, I agree with you that a polymorphic internal type for the module is totally fine. Even for modules like List, we don’t need to specialize the to IntList modules for operating on the int list type.