我是 OCaml 新手,在理解模块类型如何工作方面遇到了一些困难。
module type I = sig
type t
end
module EQ (M : I) = struct
let equal (x : M.t) (y : M.t) = x = y
end
(* Explicitly type declaration *)
module A : I = struct
type t = string
end
module EStr1 = EQ (A)
(* Error: This expression has type string but an expression was expected of type
A.t *)
let _ = EStr1.equal "1" "0" |> string_of_bool |> print_endline
(* No type declaration *)
module B = struct
type t = string
end
module EStr2 = EQ (B)
(* OK. Outputs false *)
let _ = EStr2.equal "1" "0" |> string_of_bool |> print_endline
在上面的代码中,我声明了模块类型 I,模块 A 具有显式模块类型声明,模块 B 没有模块类型声明。 EQ 是函子,接收类型 I 的模块并以 equal 方法返回模块。 模块 A 的示例导致编译错误,而其他模块按我的预期工作。这个例子之间的语义差异是什么?
顶级解释器的输出很有启发性。
# module type I = sig
type t
end
module EQ (M : I) = struct
let equal (x : M.t) (y : M.t) = x = y
end
(* Explicitly type declaration *)
module A : I = struct
type t = string
end
module EStr1 = EQ (A);;
module type I = sig type t end
module EQ : functor (M : I) -> sig val equal : M.t -> M.t -> bool end
module A : I
module EStr1 : sig val equal : A.t -> A.t -> bool end
注意
EStr1
模块的签名。 EStr1.equal
的类型为 A.t -> A.t -> bool
。不输入 string -> string -> bool
。
将
I
签名应用于 A
限制了我们了解 A.t
是什么。它是一个抽象类型。您还没有对 B
执行此操作,因此 EStr2.equal
确实具有类型 string -> string -> bool
。
您还可以显式公开此类型信息。
# module A : I with type t = string = struct
type t = string
end;;
module A : sig type t = string end
# module C = EQ (A);;
module C : sig val equal : string -> string -> bool end