首先,你不能有被命名相同的多个构造数据类型。一个将不可避免地影响另一个。是你运行该代码,你会得到一个警告类似于:
! datatype tree = Empty
! | Leaf of leaf
! | Node of leaf * 'a tree
! | Node of leaf * 'a tree * 'a tree
! | Node of leaf * 'a tree * 'a tree * 'a tree
! Unguarded type variables at the top-level
这是因为定义使用未声明为树类型的一部分类型参数'a
。这个改变成datatype 'a tree = ...
,而不是你得到这个错误:
! | Node of leaf * 'a tree * 'a tree
! ^^^^
! Illegal constructor specification: the constructor cannot be specified twice for the same datatype
你可以做什么,而不是是有三种不同的构造,例如
datatype 'a tree = Empty
| Node0 of leaf
| Node1 of leaf * 'a tree
| Node2 of leaf * 'a tree * 'a tree
| Node3 of leaf * 'a tree * 'a tree * 'a tree
Are my datatypes the best way to represent the tree?
是的,你的数据类型是非常精细的。
How do I make my function recursively go through the tree?
你可以用不同的方式浏览一棵树。见tree traversal和folding a tree。
in a list, you can do hd::tl
, is there a way I can do that on the tree so that, having gone through the node, I call the function on each node?
您可以创建一个paramorphic功能一样折叠,但在参数化功能需要整个节点而不仅仅是元素的节点作为参数:
fun para f e t =
let val e1 = f (e, t)
in case t of
Empty => e1
| Node0 x => e1
| Node1 (x, t1) => para f e1 t1
| Node2 (x, t1, t2) => para f (para f e1 t1) t2
| Node3 (x, t1, t2, t3) => para f (para f (para f e1 t1) t2) t3
end
计数节点的数量与1,2和3的子树是这样的功能的特化:
fun nodecount t =
let fun helper ((one, two, three), t) =
case t of
Empty => e1
| Node0 _ => (one, two, three)
| Node1 _ => (one+1, two, three)
| Node2 _ => (one, two+1, three)
| Node3 _ => (one, two, three+1)
in para helper (0,0,0) t end
编辑:是的,数据类型上面,其实是多余的,因为可以精确到一个叶一树x
可以写成:
val one_leaf = Node0 (x)
val one_leaf = Node1 (x, Empty)
val one_leaf = Node2 (x, Empty, Empty)
val one_leaf = Node3 (x, Empty, Empty, Empty)
如果删除Empty
,这种冗余会消失,但你可以不再代表空树。一个简单的方法来克服,这是通过使用两种类型:
datatype 'a tree = Empty | NonEmpty of 'a tree_aux
and 'a tree_aux = Node0 of leaf
| Node1 of leaf * 'a tree_aux
| Node2 of leaf * 'a tree_aux * 'a tree_aux
| Node3 of leaf * 'a tree_aux * 'a tree_aux * 'a tree_aux
或者如果你喜欢较少的构造函数和一个预先存在的人组成类型:
datatype leaf = Slist of string list | Real of real;
datatype 'a tree = Empty | NonEmpty of 'a tree_aux
and 'a tree_aux = Node of leaf * ('a tree_aux * ('a tree_aux * 'a tree_aux option) option) option
但这是稍微麻烦。
再次感谢您回答这个问题,我修改了我在这方面的内容,发现'datatype leaf = Slist of string list |真实的; datatype'a tree = Empty |叶的叶|叶节点*'一棵树*'一棵树*'一棵树;'起作用,但我也会试验你的。我对你的答案有同样的推理,在这里我使用了这些案例,但是你对Node(i)的使用似乎更有效率。唯一的问题是,当它有三个节点并且最终将它们全部添加时递归地通过它。看起来你的答案似乎不止一层,但确实证实了事情 –