Types 为什么在Ocaml中使用模块类型?

Types 为什么在Ocaml中使用模块类型?,types,functional-programming,ocaml,Types,Functional Programming,Ocaml,我混淆了Ocaml中的模块类型 我想知道在哪种情况下我们应该使用模块类型? 我通常使用.mli中的模块sig来公开一些细节,并将 .ml中对应的实现模块结构 例如: mli先生 .ml 因此,我认为Ocaml的模块类似于c中的.h和.c文件 我知道模块类型可以声明接口,但是接口与Java的接口不同 就像书中的一个例子: open Core.Std module type ID = sig type t val of_string : string -> t val to_

我混淆了Ocaml中的模块类型

我想知道在哪种情况下我们应该使用模块类型?

我通常使用.mli中的模块sig来公开一些细节,并将 .ml中对应的实现模块结构

例如:

mli先生

.ml

因此,我认为Ocaml的模块类似于c中的.h和.c文件

我知道模块类型可以声明接口,但是接口与Java的接口不同

就像书中的一个例子:

open Core.Std

 module type ID = sig
  type t
   val of_string : string -> t
  val to_string : t -> string
 end

  module String_id = struct
   type t = string
    let of_string x = x
    let to_string x = x
  end

  module Username : ID = String_id
  module Hostname : ID = String_id

  type session_info = { user: Username.t;
                  host: Hostname.t;
                  when_started: Time.t;
                }

  let sessions_have_same_user s1 s2 =
       s1.user = s2.host
前面的代码有一个bug:它将一个会话中的用户名与另一个会话中的主机进行比较,而在这两种情况下都应该比较用户名

模块类型似乎不能为其实现提供新的通用超类型

模块类型的实际应用与什么密切相关。阅读第章

函子的参数具有某种模块类型,其结果也是如此

函子被大量使用,大多数标准容器(如-s或-s)都是函子

如果开发泛型容器,您肯定需要函子和模块类型


(因此,函子和模块类型在Ocaml中的用处与模板在C++中的用处一样大)

这里,模块类型用于向模块用户隐藏类型
t

当使用
Username.t
Hostname.t
时,不能依赖于字符串、整数或任何特定类型。模块类型使它们不透明,好像它们不是模块接口的一部分,而只是模块编写器将来将要更改的实现细节

基本上,模块用户只能通过模块功能对类型
t
进行操作


编译器检查用户代码是否没有对这些类型
t
实际是什么进行任何假设,以便将来模块编写器可以在不破坏用户代码的情况下更改它们。

如前所述,这里使用模块类型来实现类型
t
的更抽象的视觉。当您将
用户名
主机名
定义为两个独立的模块时,这意味着它们在逻辑上必须不同,并且这些模块的签名是使用它们的唯一可能方式

但你说的是错的:

似乎模块类型不能为应用程序提供新的通用超级类型 这是执行

实际上,您可以确定
Username.t
Hostname.t
是相同的类型

module Username = (String_id : ID with type t = String_id.t)
module Hostname = (String_id : ID with type t = String_id.t)

Username.to_string (Hostname.of_string "hi")

在这里它是无用的,但有时它真的很有用。

我假设,如果我的目的是隐藏一些细节,模块sig就足够了。Username.t和Hostname.t的通用超级类型是什么?我假设Ocaml不能与模块类型匹配。@qc1iu没有常见的超类型。毕竟,其中一个可能是
string
,另一个可能是
int
。作为模块的用户,您无法看到确切的类型,只能利用模块提供的函数来处理该(抽象)类型。
open Core.Std

 module type ID = sig
  type t
   val of_string : string -> t
  val to_string : t -> string
 end

  module String_id = struct
   type t = string
    let of_string x = x
    let to_string x = x
  end

  module Username : ID = String_id
  module Hostname : ID = String_id

  type session_info = { user: Username.t;
                  host: Hostname.t;
                  when_started: Time.t;
                }

  let sessions_have_same_user s1 s2 =
       s1.user = s2.host
module Username = (String_id : ID with type t = String_id.t)
module Hostname = (String_id : ID with type t = String_id.t)

Username.to_string (Hostname.of_string "hi")