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

Hello,

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?

Thanks.

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
end

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.

Thanks.