2012-07-31 82 views
5

我发现了一些在处理ocaml项目时并不了解的东西。ocaml中的模块化编程

假设我使用OCaml标准库的ArrayList模块。它们都执行功能length但具有不同的类型。 在List模块,这是它的类型:

length: a' list -> int 

而且Array模块中,它具有类型:

length: a' array -> int 

但后来我想,你在同一个模块我是在用这两个模块实施,通过open关键字:

open List 
open Array 

当我试图用在了length功能列表中,编译期间出现类型错误。
由于OCaml是一个强大的静态类型语言,我想知道为什么编译器不知道我想要列表模块的长度函数,因为我声明我正在使用两者。

+1

“我想知道为什么编译器不知道我想要列表模块的长度函数,因为我声明我同时使用了”是的,但是什么类型的'fun s - > length s'在这种情况呢? – 2012-07-31 09:33:28

+0

基于jrouquie的答案,它会是'a'array - > int' – 2012-07-31 09:52:56

+1

准确地说,但是在假设的OCaml编译器试图猜测的情况下,在OCaml类型系统中不会有单个最通用的类​​型为功能。您可能会对Haskell的解决方案感兴趣,请输入类:http://www.haskell.org/tutorial/classes.html – 2012-07-31 11:32:54

回答

8

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

当你写模块Array

open Array 

的功能名称相同的屏蔽模块List的人。 当您稍后调用函数length时,OCaml查找名为length的函数,找到Array.length,并且抱怨此函数没有兼容类型。

通常的方法是打电话List.length(而不是只是length),如果这是你需要的功能。更一般地说,OCaml没有名称重载(即具有两个函数或具有相同名称但不同参数类型的操作符),特别是因为这会使得类型推断困难得多。

+2

另外:尽量避免打开模块 - 它会让读取代码变得更加困难,因为读者必须记住哪些模块已打开(以及按照哪个顺序);也作为一个读者,你不能立即意识到一个函数来自哪里(从哪个开放的模块是)。 – lambdapower 2012-07-31 14:42:48

+2

我想补充说,如果使用的值/函数的原点保持清晰,那么打开模块就没有问题。因此,不要打开像List或Array这样的提供泛型名称功能的模块,但是“打开Printf”是完全正确的,因为它提供了源自显而易见的函数printf,fprintf等。 – 2012-07-31 17:15:21