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