I am following the example here.
module IntPairs =
struct
type t = int * int
let compare (x0,y0) (x1,y1) =
match Stdlib.compare x0 x1 with
| 0 -> Stdlib.compare y0 y1
| c -> c
end
module PairsMap = Map.Make(IntPairs)
let m = PairsMap.(
empty
|> add (0,1) "hello"
|> add (1,0) "world"
)
My question is, why the code doesn't compile when I add : Map.OrderedType
to the module IntPairs
definition? Like this:
module IntPairs : Map.OrderedType =
struct
type t = int * int
let compare (x0,y0) (x1,y1) =
match Stdlib.compare x0 x1 with
| 0 -> Stdlib.compare y0 y1
| c -> c
end
module PairsMap = Map.Make(IntPairs)
let m = PairsMap.(
empty
|> add (0,1) "hello"
|> add (1,0) "world"
)
Error message:
64 | let m = PairsMap.(empty |> add (0, 1) "hello" |> add (1, 0) "world")
^^^^^^
Error: This expression has type 'a * 'b
but an expression was expected of type
key
Isn't IntPairs
expected to implement the module type Map.OrderedType
?
When you specify the type Map.OrderedType
you make the type of the key abstract because that module signature doesn't tell us anything about type t
. Instead, expose the type of t
explicitly and you'll find your code works.
module IntPairs : Map.OrderedType with type t = int * int =
struct
type t = int * int
let compare (x0,y0) (x1,y1) =
match Stdlib.compare x0 x1 with
| 0 -> Stdlib.compare y0 y1
| c -> c
end
Or taking advantage of the fact that Stdlib.compare
already works this way for tuples of ints.
module IntPairs : Map.OrderedType with type t = int * int =
struct
type t = int * int
let compare = Stdlib.compare
end
It may disambiguate the syntax here to add a set of parentheses.
module IntPairs : (Map.OrderedType with type t = int * int) =
...
As noted in comments, the other option is simply not to restrict the type of IntPairs
at all.
module IntPairs =
struct
type t = int * int
let compare = Stdlib.compare
end
module PairsMap = Map.Make (IntPairs)