模块<name> = struct .. end和模块类型<name> = struct .. end?</name> </name>之间的区别

时间:2010-10-28 11:35:03

标签: module ocaml

module <name> =
   struct 
     .. 
   end;;


module type <name> =
    struct (* should have been sig *)
      .. 
end;;

3 个答案:

答案 0 :(得分:8)

第一个声明一个模块,第二个声明一个模块类型(又称签名)。模块类型包含typeval声明,而模块可以包含定义(例如,let绑定)。您可以使用签名来限制模块的类型,就像对功能一样。例如,

module type T = sig
  val f : int -> int
end

module M : T = struct
  let f x = x + 1
  let g x = 2 * x
end

现在,我们有

# M.f 0 ;;
- : int = 1
# M.g 0 ;;
Error: Unbound value M.g

M.g未绑定,因为它已被签名T隐藏。

使用模块类型的另一种常用方法是作为参数并返回仿函数的值。例如,the standard library中的Map.Make仿函数采用带有签名Map.OrderedType的模块,并创建一个带有签名Map.S的模块

P.S。请注意,问题中存在错误。使用

声明模块类型
module type <name> = sig
  ...
end

答案 1 :(得分:4)

结构(书面struct … end)是一堆定义。可以在模块中定义语言中的任何对象:核心值(let x = 2 + 2),类型(type t = int),模块(module Empty = struct end),签名(module type EMPTY = sig end)等。模块是结构的概括:结构是一个模块,因此是仿函数(将其视为一个将模块作为参数并返回一个新函数的函数模块)。模块就像核心价值,但实际上是一层:模块可以包含任何东西,而核心价值只能包含其他核心价值¹。

签名(书面sig … end)是一堆规范(某些语言使用术语声明)。可以在模块中指定语言中的任何对象:核心值(val x : int),类型(type t = int),模块(module Empty : sig end),签名(module type EMPTY = sig end)等。模块类型概括签名:模块类型指定模块,恰好指定结构的模块类型称为签名。模块类型是模块,普通类型是核心值。

编译单元(.ml文件)是结构。接口(.mli文件)是签名。

所以module Foo = struct … end定义了一个名为Foo的模块,它恰好是一个结构。这类似于let foo = (1, "a"),它定义了一个名为foo的值,恰好是一对。而module type FOO = sig … end(注意:sig,而不是struct)定义了一个名为FOO的模块类型,它恰好是一个签名。这类似于type foo = int * string,它定义了一个名为foo的类型,恰好是产品类型。

¹ 事实上这已不再适用,因为OCaml 3.12引入了一流的模块,但它足够接近介绍性演示。

答案 2 :(得分:0)

模块类型描述模块。它与.ml和.mli

之间的区别相同