Home > Back-end >  Why does a module type annotation in OCaml cause this code to not compile?
Why does a module type annotation in OCaml cause this code to not compile?

Time:12-11

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
  • Related