Suppose I have a number of modules that are all parameterized with one module type, and also have dependencies between each other:
module type AT = sig
end
module B(A: AT) = struct
module Hash = struct
type t = int
let equal b1 b2 = b1 = b2
let hash b = b
end
end
module C(A: AT) = struct
module B = B(A)
module Hashtbl = Hashtbl.Make(B.Hash)
let make () = Hashtbl.create 16
end
module D(A: AT) = struct
module B = B(A)
module Hashtbl = Hashtbl.Make(B.Hash)
let use ht =
Hashtbl.clear ht
end
module E(A: AT) = struct
module C = C(A)
module D = D(A)
let f () =
D.use (C.make ())
end
Here, everything is parameterized with AT
. Then, C
and D
are independent, and E
depends on C
and D
. This code does not compile, since the compiler is not convinced that inside E
, C.Hashtbl
and D.Hashtbl
are the same module:
File "xxxx.ml", line xx, characters xx-xx:
Error: This expression has type 'a C.Hashtbl.t = 'a Hashtbl.Make(C.B.Hash).t
but an expression was expected of type
'b D.Hashtbl.t = 'b Hashtbl.Make(D.B.Hash).t
Is there a quick way to convince ocaml that the two hashset modules are the same?
The typechecker is right that the two
Hashtbl
modules are not the same and should not be mixed together: consider for instance a slightly modifiedB
module:Then the two instances
C.B
andD.B
of the functor applicationF(A)
do not share the same salt. Consequently, mixing hash tables derived fromC.B.Hash
andD.B.Hash
would be an error that leads to a completely erratic behavior.