我尝试在OCaml中使用参数化类型,但它不起作用:(
在第一个文件" tree.ml"我定义了类型:
type 'a tree =
| Node of ('a tree)*('a tree)
| Leaf of 'a
在另一个文件" intTree.ml"中,我使用此类型来定义类型t:
open Tree
type t = int tree
最后,我想在函数中使用类型t" size" in" main.ml" :
open IntTree
type r = IntTree.t
let rec size tree = match tree with
| Leaf k -> 0
| Node (t1,t2) -> 1 + size t1 + size t2
当我尝试编译这些文件时,我收到以下错误:
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.
...
我知道它们是快速解决此错误的解决方案(例如,将#34;打开树类型t = int树"在main.ml而不是"打开IntTree类型t = IntTree.t& #34;)但我需要使用以前的结构(出于其他原因......)。有解决方案吗?
谢谢
答案 0 :(得分:5)
你需要在main.ml中open Tree
。您不需要复制和粘贴类型声明。在你的代码编译器试图猜测你的想法。这就是为什么手动添加类型注释部分解决问题的原因。
编译器发现您希望tree
属于r
类型,它会查看模块r
中的类型IntTree
(由您打开)并在那里了解可能我们在Tree
模块中有这个构造函数。它会打开警告。这个功能最近才推出,所以不要因为你没有意识到这一点。
答案 1 :(得分:4)
另一个解决方案是改变这个:
open Tree
到此:
include Tree
intTree.ml
中的。我们的想法是intTree
通过包含Tree
中的所有定义而变为自包含。
答案 2 :(得分:0)
在" main.ml"中添加open Tree
将解决问题,可能最好写下以避免污染" main.ml"来自" Tree.mli"的最终无关定义:
let rec size tree = match tree with
| Tree.Leaf k -> 0
| Tree.Node (t1,t2) -> 1 + size t1 + size t2