问题
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?
回答1:
The typechecker is right that the two Hashtbl modules are not the same and should not be mixed together: consider for instance a slightly modified B module:
module B(A: AT) = struct
module Hash = struct
let y = Random.int 10
type t = int
let equal b1 b2 = b1 = b2
let hash b = b + y
end
end
Then the two instances C.B and D.B of the functor application F(A) do not share the same salt. Consequently, mixing hash tables derived from C.B.Hash and D.B.Hash would be an error that leads to a completely erratic behavior.
来源:https://stackoverflow.com/questions/48693701/how-to-convince-ocaml-that-two-functor-instantiations-are-equal