我正在将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
,它是文件的封闭模块。
答案 0 :(得分:4)
对于SML,文件及其名称都没有太大的意义。它们只是将较大的源分割成较小的单元的一种方法。由多个文件组成的程序等效于以适当的顺序串联这些文件。
这与OCaml不同,在OCaml中,每个.ml文件本身都被视为从文件名派生的名称结构,而每个相关的.mli文件(如果存在)都被视为该结构上的不透明签名注释。>
(Moscow ML基于OCaml运行时的早期实现,是使用类似文件模型的一种SML实现。)
因此,在将SML文件移植到OCaml时,您有两个基本选择:
对其进行处理,就好像它被包裹在一个额外的结构中一样。例如,您的table.sig
可能会变成table_sig.ml
(而不是.mli
!),签名将被称为Table_sig.TABLE
,而table.ml
将会变成{{1 }},并且将函子称为table_fn.ml
。
有时您需要稍微重新组织文件结构。例如,您可以选择只包含一个包含签名和函子的Table_fn.IntMapTable
来代替两个模块Table_sig
和Table_fn
。然后,OCaml倾向于使用诸如调用签名Table
和函子S
之类的命名约定,从而在其他地方将它们直观地称为Make
和Table.S
。
在某些情况下,您可以弄平这种额外的包装器结构。特别是:
a。如果文件由RHS为Table.Make
表达式的单个结构声明组成,则可以将其主体放在以声明的结构命名的.ml文件中。
b。如果该文件由RHS是struct
表达式的单个签名声明组成,并且仅根据情况(a)使用一次来对结构进行注释,则可以将其主体放在名为.mli的文件中在相应结构之后。
第二种是常见情况。