模块和存在之间的区别

时间:2015-03-13 02:13:40

标签: module ocaml existential-type

民间知识,OCaml模块是“只是”存在类型。

之间存在某种奇偶性
module X = struct type t val x : t end

data 'a spec = { x : 'a }
data x = X : 'a spec

这并非完全不真实。

但正如我刚才所证明的那样,OCaml有模块和存在类型。我的问题是:

  • 他们有何不同?
  • 有什么可以在一个而不是另一个中实现吗?
  • 您何时使用其中一个(特别是将一流模块与存在类型进行比较)?

2 个答案:

答案 0 :(得分:4)

它是具有存在类型的特定抽象类型。我认为没有抽象类型的模块可以在没有存在的情况下解释。

模块具有抽象类型以外的功能:它们充当命名空间,结构类型,支持includemodule type of等操作,它们允许私有类型等。

一个显着的区别是,仿函数允许范围超过任何(固定)arity的类型,这对于类型变量是不可能的,因为OCaml缺少更高的kinded类型:

module type M = sig
  type 'a t
  val x : 'a t
end

我不太清楚如何回答你的上一个问题。模块和存在体在实践中是不同的,以至于何时用一个替换另一个的问题还没有出现。

答案 1 :(得分:4)

在第三点完成gsg的答案。

使用模块有两种方式:

  • 作为结构化构造,当您声明顶层模块时。在这种情况下,你并没有真正操纵存在变量。在system-F中对模块系统进行编码时,您可以通过存在变量有效地表示抽象类型,但在道德上,它更接近于新的单例类型。

  • 作为值,使用first class modules时。在这种情况下,你显然在操纵存在类型。

存在类型的其他表示是通过GADT's和对象。 (也可以将存在性编码为带记录的通用否定,但它的用法完全被第一类模块所取代。)

在这三种情况之间进行选择取决于上下文。 如果要为类型提供许多功能,则更喜欢模块或对象。如果只有少数几个,您可能会发现模块或对象的语法太重,而且更喜欢GADT。 GADT还可以显示您的类型的结构,例如:

type _ ty =
  | List : ty -> ty list
  | Int : int list

type exist = E : 'a ty * 'a -> exist

如果你遇到这种情况,你不需要传播那种类型的函数,所以你最终会得到更轻松的GADT存在的东西。使用模块,这看起来像

module type Exist = sig
  type t
  val t : t ty
end
module Int_list : Exist = struct
  type t = int list 
  let t = List Int
end
let int_list = (module Int_list:Exist)

如果您需要子类型或后期绑定,请转到对象。这通常可以用模块编码,但这往往很乏味。

相关问题