Types OCaml中的参数化类型

Types OCaml中的参数化类型,types,ocaml,parameterized,Types,Ocaml,Parameterized,我尝试在OCaml中使用参数化类型,但不起作用:( 在第一个文件“tree.ml”中,我定义了类型: type 'a tree = | Node of ('a tree)*('a tree) | Leaf of 'a 在另一个文件“intTree.ml”中,我使用此类型定义类型t: open Tree type t = int tree 最后,我想在“main.ml”中的函数“size”中使用类型t: 当我试图编译这些文件时,我得到以下错误: File "main.ml", l

我尝试在OCaml中使用参数化类型,但不起作用:(

在第一个文件“tree.ml”中,我定义了类型:

type 'a tree =
  | Node of ('a tree)*('a tree) 
  | Leaf of 'a  
在另一个文件“intTree.ml”中,我使用此类型定义类型t:

open Tree
type t = int tree
最后,我想在“main.ml”中的函数“size”中使用类型t:

当我试图编译这些文件时,我得到以下错误:

File "main.ml", line 6, characters 4-8:
Error: Unbound constructor Leaf
如果我定义了“main.mli”,它不会改变任何东西:

type r

val size : r -> int
如果我说:

let rec size (tree : r) = match tree with
  | Leaf k -> 0
  | Node (t1,t2) -> 1 + size t1 + size t2
我有:

Warning 40: Leaf was selected from type Tree.tree.
It is not visible in the current scope, and will not 
be selected if the type becomes unknown.
...
我知道它们是快速解决此错误的解决方案(例如,在main.ml中放置“open-Tree-type t=int-Tree”而不是“open-int-Tree-type t=int-Tree.t”),但我需要使用前面的结构(出于其他原因…),有解决方案吗


谢谢

您需要
在main.ml中打开树
。您不需要复制和粘贴类型声明。在您的代码中,编译器尝试猜测您的想法。这就是为什么手动添加类型注释部分解决了问题


编译器看到您期望
tree
r
类型,它从模块
IntTree
中查看类型
r
(由您打开)在那里,它了解到可能我们在
模块中有此构造函数。它打开时会发出警告。此功能是最近引入的,因此不要担心您没有意识到它。

另一个解决方案是更改此选项:

open Tree
为此:

include Tree

intTree.ml
中,想法是
intTree
通过包含
Tree

中的所有定义而变得自包含。在“main.ml”中添加
opentree
将解决此问题,最好编写以下内容以避免污染“main.ml”使用“Tree.mli”中最终不相关的定义:


你的
main.ml
打开
IntTree
,因此它得到了所有在那里定义的名称。然而,
Leaf
没有在那里定义;它是在
树中定义的。因此,正如Kadaku所说,你应该在
main.ml
中打开
树。这看起来很麻烦,但那是因为你的模块太小了。在真正的pr中您将有更多的名称需要控制。此外,我个人发现,在大型项目中使用完全限定的名称,
Tree.Leaf
,比打开名称更有帮助。
include Tree
let rec size tree = match tree with
  | Tree.Leaf k -> 0
  | Tree.Node (t1,t2) -> 1 + size t1 + size t2