标准 ML 实现文件中的定义在外部可见(但不在签名文件中)



我正在将 SML 起始代码从 Tiger 书转换为 OCaml。

让我感到困惑的是,在签名文件table.sig(下图(中,没有提到IntMapTable ,但函子可以在另一个文件中访问,无需任何限定。

(* table.sig *)
signature TABLE =
sig
    ...
end
(* table.sml *)
functor IntMapTable (...) : TABLE =
struct
...
end
(* symbol.sml *)
...
structure Table = IntMapTable(...)
...

我的理解是,只有.sig文件中的代码可以访问外部模块,而不能访问.sml文件中的代码。难道不是这样吗?

另外,OCaml 中的等效代码可能是什么样子的?这很尴尬,因为函子IntMapTable的结果类型是 Table ,这是文件的封闭模块。

对于 SML,文件及其名称都没有多大意义。它们只是将较大的来源切成更小单元的一种方式。由多个文件组成的程序等效于以某种合适的顺序连接这些文件。

这在 OCaml 中有所不同,其中每个 .ml 文件本身都被视为从文件名派生的名称的结构,而每个关联的 .mli 文件(如果存在(都被视为该结构上的不透明签名批注。

(Moscow ML基于OCaml运行时的早期实现,是使用类似文件模型的SML实现。

因此,将 SML 文件移植到 OCaml 时,您有两个基本选择:

  1. 将其视为包裹在额外的结构中。例如,您的table.sig可能会变得table_sig.ml(而不是.mli!(,并且签名将被称为Table_sig.TABLE,而table.ml将变得table_fn.ml函子被称为Table_fn.IntMapTable

    有时您想稍微重新组织一下文件结构。例如,与其有两个模块Table_sigTable_fn,你可以选择只有一个同时包含签名和函子的Table。OCaml倾向于使用命名约定,如调用签名S和函子Make,因此直观地将它们称为Table.S和其他地方Table.Make

  2. 在某些情况下,您可以展平这个额外的包装器结构。特别:

    一个。如果文件由单个结构声明组成,其 RHS 是struct表达式,则可以将其正文放在以声明的结构命名的 .ml 文件中。

    二.如果文件由单个签名声明组成,其 RHS 是sig表达式,并且根据大小写 (a( 仅使用一次来注释结构,则只需将其正文放在以相应结构命名的 .mli 文件中即可。

第二种往往是常见情况。

最新更新