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

时间:2018-08-09 05:56:57

标签: ocaml sml tiger

我正在将SML入门代码从Tiger book转换为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,它是文件的封闭模块。

1 个答案:

答案 0 :(得分:4)

对于SML,文件及其名称都没有太大的意义。它们只是将较大的源分割成较小的单元的一种方法。由多个文件组成的程序等效于以适当的顺序串联这些文件。

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

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

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

  1. 对其进行处理,就好像它被包裹在一个额外的结构中一样。例如,您的table.sig可能会变成table_sig.ml(而不是.mli!),签名将被称为Table_sig.TABLE,而table.ml将会变成{{1 }},并且将函子称为table_fn.ml

    有时您需要稍微重新组织文件结构。例如,您可以选择只包含一个包含签名和函子的Table_fn.IntMapTable来代替两个模块Table_sigTable_fn。然后,OCaml倾向于使用诸如调用签名Table和函子S之类的命名约定,从而在其他地方将它们直观地称为MakeTable.S

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

    a。如果文件由RHS为Table.Make表达式的单个结构声明组成,则可以将其主体放在以声明的结构命名的.ml文件中。

    b。如果该文件由RHS是struct表达式的单个签名声明组成,并且仅根据情况(a)使用一次来对结构进行注释,则可以将其主体放在名为.mli的文件中在相应结构之后。

第二种是常见情况。