首先,你不能有被命名相同的多個構造數據類型。一個將不可避免地影響另一個。是你運行該代碼,你會得到一個警告類似於:
! 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)的使用似乎更有效率。唯一的問題是,當它有三個節點並且最終將它們全部添加時遞歸地通過它。看起來你的答案似乎不止一層,但確實證實了事情 –