OCaml中模块中的抽象类型

时间:2018-01-24 22:42:47

标签: module ocaml signature

我在OCaml中有非​​常简单的签名和模块:

module type S = sig
  type t 
  val y : t
end;;

module M2 : S = struct
  type t = int
  let x = 1
  let y = x+2
end;;

我不能使用像

这样的结构
M2.y
除非我将模块指定为

,否则

获取3

module M2 : S with type t = int = struct ...

为什么会这样?已有声明type t = int

1 个答案:

答案 0 :(得分:3)

int的具体M2.y值确实无效,因为满足以下两个条件:

  1. 签名yS的类型为抽象 (那里没有type t = ...

  2. 模块M2相对于签名S 不透明 (换句话说,它仅限于签名S 通过符号: S

  3. 结果,你确实获得了:

    let test = M2.y ;;
    (* val test : M2.t = <abstr> *)
    

    根据关键字<abstr>的建议,这与抽象类型的概念有关。这个概念是OCaml的输入规则强制执行的一个非常强大的功能,它可以防止具有签名S的模块的任何用户检查这种抽象类型的具体内容。因此,通过仔细分离ADT的实现和签名,此属性对于在OCaml中实现所谓的abstract data types (ADT)非常有用。

    如果缺少上述两个条件中的任何一个,则类型将不再是抽象的,并且y的具体值将显示出来。

    更确切地说:

    1. 如果类型t具体化,则获得:

      module type S = sig
        type t = int
        val y : t
      end
      
      module M2 : S = struct
        type t = int
        let x = 1
        let y = x+2
      end
      
      let test = M2.y ;;
      (* val test : M2.t = 3 *)
      

      但在实践中,这并不是很有趣,因为你失去了普遍性。然而,一个更有趣的方法是在签名中添加“评估者”或“漂亮的打印机”功能,例如下面的值int_of_t

      module type S = sig
        type t
        val y : t
        val int_of_t : t -> int
      end
      
      module M2 : S = struct
        type t = int
        let x = 1
        let y = x+2
        let int_of_t x = x
      end
      
      let test = M2.(int_of_t y) ;;
      (* val test : int = 3 *)
      
    2. 否则,如果模块M2变为透明,则获得:

      module type S = sig
        type t
        val y : t
      end
      
      module M2 (* :S *) = struct
        type t = int
        let x = 1
        let y = x+2
      end
      
      let test = M2.y ;;
      (* val test : int = 3 *)
      
    3. 最后,注意除了抽象类型的特征之外,OCaml还提供了私有类型的功能,可以将其视为在具体和抽象类型之间的权衡。模块化开发。有关此概念的更多详细信息,请参阅示例Chap. 8 of Caml ref man

      希望这有帮助