ocaml中的模块化编程

Jos*_*cid 5 ocaml types namespaces module

我在ocaml项目工作中发现了一些我不太懂的东西.

假设我正在使用OCaml标准库的模块ArrayList模块.它们都实现了功能length但具有不同的类型.在List模块中,这是它的类型:

length: a' list -> int
Run Code Online (Sandbox Code Playgroud)

Array模块中,它具有以下类型:

length: a' array -> int
Run Code Online (Sandbox Code Playgroud)

但后来我希望你通过open关键字在我实现的同一个模块中使用这两个模块:

open List
open Array
Run Code Online (Sandbox Code Playgroud)

当我尝试length在列表上使用该函数时,我在编译期间遇到了类型错误.
由于OCaml是一种强大的静态类型语言,我想知道为什么编译器不知道我想要列表模块的长度函数,因为我声明我正在使用它们.

jro*_*uie 8

OCaml不会根据其类型选择一个或另一个函数.

当你写作

open Array
Run Code Online (Sandbox Code Playgroud)

模块的功能Array是屏蔽List具有相同名称的模块.当您稍后调用该函数时length,OCaml会查找名为length,查找Array.length和抱怨此函数没有兼容类型的函数.

通常的方法是调用List.length(而不是仅仅length),如果这是你需要的功能.


更常见的是,OCaml没有名称重载(即具有两个具有相同名称但具有不同参数类型的函数或运算符),特别是因为这会使类型推断更加困难.

  • 另外:尽量避免打开模块 - 它会使阅读代码变得更加困难,因为读者必须记住哪些模块是打开的(以及以何种顺序); 作为一个读者,你没有立即意识到函数的来源(来自哪个open-ed模块). (2认同)
  • 我想补充说,如果使用的值/函数的来源仍然清晰,那么打开模块就可以了.所以不要打开像List或Array那样提供通用名称功能的模块,但是"open printf"完全没问题,因为它提供了起源很明显的printf,fprintf等功能. (2认同)