It’s definitely true that the documentation around Map is insufficient. We’re working on it, and I also hope to refresh the chapter in RWO to cover the way Maps now work in Base (and will soon work in Core as well.)
It’s definitely most convenient if you use Base’s Int module, but it’s easy enough to do it with your own module.
module Foo = struct
module T = struct
type t = int * int
let compare x y = Tuple2.compare Int.compare Int.compare
let sexp_of_t = Tuple2.sexp_of_t Int.sexp_of_t Int.sexp_of_t
end
include T
include Comparable.Make(T)
end
Gives you a module Foo with the appropriate comparator in it, and then this:
let m = Map.empty (module Foo)
lets you create a module keyed by Foo. You need to write a sexp-converter and a comparison function for this to work, because maps both need comparison and the ability to serialize the key for generating useful errors. It’s of course nicer to do this with the appropriate PPXs:
module Foo = struct
module T =
struct type t = int * int [@@deriving sexp_of, compare] end
include T
include Comparable.Make(T)
end
There’s no soundness issue, because the functor mints a fresh type each time it’s called on a different input module, ensuring that different comparison functions have distinct type witnesses.
y