I am working with the Map module in OCaml. Consider the following code to create a map with ints as keys:
module Int = struct
type t = int
let compare a b = a - b
end
module IntMap = Map.Make(Int)
let m = IntMap.(empty |> add 3 "hello")
This all works fine. It compiles and behaves as I would expect.
However, if I add a type annotation for the Int module so the top line becomes:
module Int : Map.OrderedType = struct
The final line causes an error in compilation:
let m = IntMap.(empty |> add 3 "hello")
^
Error: This expression has type int but an expression was expected of type
IntMap.key = Int.t
However IntMap.key and Int.t are both just an alias for int. Furthermore the Int module is of type Map.OrderedType. I know this because that's the required type for Map.Make.
So what an earth is going on here? Why would providing a type annotation that isn't necessary cause an error like this. Do type annotations cause stricter accessibility and not behave the same as inferred types?
CodePudding user response:
This kind of annotation strictly limits the interface of a module. So it seems to me that with the added annotation the only things known about the key type of the map are as given by Map.OrderedType:
module type OrderedType =
sig type t val compare : t -> t -> int end
This says nothing about the type t except that it exists and that it appears in the parameters of compare. In other words, you have hidden the fact that the type t (also known as IntMap.key) is the same type as int.
You can re-introduce this fact using with:
module Int : Map.OrderedType with type t = int = struct
type t = int
let compare a b = a - b
end
