我是 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
导致编译错误,而另一个示例则按我预期运行。这些示例之间的语义差异是什么?
顶层解释器的输出很有启发。
注意模块的签名
EStr1
。EStr1.equal
有类型A.t -> A.t -> bool
。没有类型string -> string -> bool
。将
I
签名应用于A
限制了我们了解什么A.t
是。它是一种抽象类型。您还没有对 进行此操作B
,因此EStr2.equal
确实有 类型string -> string -> bool
。您还可以明确公开此类型信息。
一旦你理解了抽象类型的工作原理,它们就会非常有用。