如何从数据类型中提取元组?

时间:2018-10-06 00:52:36

标签: functional-programming sml

SML的新手,并尝试通过一系列练习来学习。我正在尝试编写的函数涉及将带有N个孩子的树展平。我的方法是简单地获取当前的NTreeNode并将其值添加到要返回的列表中。然后采用第二个参数,即子列表,然后将其附加到另一个列表上,这就是我的队列。此队列将用作我剩下要处理的所有项目。

我试图通过将NTreeList和我将以flattenNTree的初始值返回的列表传递给辅助函数来实现此方法。

但是,当我尝试从队列中处理NTreeNode时,它会给我返回NTree,而我无法在其上使用first / second函数,我需要从队列中返回一个元组。我只是不明白如何取回元组,我尝试使用NTreeNode构造函数,但是即使那样也给了我NTree的回馈。

我的问题是如何从已定义的NTree数据类型中提取元组。

datatype NTree =
NTreeNode of int * NTree list
| EmptyNTree
;

fun first  (a, _) = a;
fun second (_, b) = b;

fun processTree queue finalList  = 
  if null queue
   then finalList
  else processTree ((tl queue)@(second(NTreeNode(hd queue)))) finalList@[first (NTreeNode (hd queue)) ]
;
fun flattenNTree EmptyNTree = []
   | flattenNTree (NTreeNode x) = processTree (second x) [(first x)]
 ;

示例输入值:

val t =
  NTreeNode (1, [
    NTreeNode (2, [
      NTreeNode (3, [EmptyNTree]),
      NTreeNode (4, []),
      NTreeNode (5, [EmptyNTree]),
      EmptyNTree
    ]),
    NTreeNode (6, [
      NTreeNode (7, [EmptyNTree])
    ])
  ]);

3 个答案:

答案 0 :(得分:3)

通过模式匹配将事情拆散比摆弄firsttl这样的选择器要容易得多。

反向累积列表并在完成后进行修复比重复添加到列表末尾更有效。

fun processTree [] final = reverse final
  | processTree (EmptyTree::ts) final = processTree ts final
  | processTree ((NTreeNode (v,t))::ts) final = processTree (ts @ t) (v :: final)

答案 1 :(得分:2)

您的processTree函数缺少EmptyNTree的大小写,并且您似乎在尝试调用NTreefirst之前添加second构造函数,而您就像在flattenNTree中一样,需要删除它们。

可以通过将模式匹配应用于队列开头来解决这两个问题:

fun processTree queue finalList =
  if null queue
  then finalList
  else case hd queue of
         EmptyNTree => processTree (tl queue) finalList
       | NTreeNode v => processTree (tl queue @ second v) (finalList @ [first v])
;

您可能还会考虑基于列表功能的实现(尽管结果的顺序不同):

fun flattenNTree t = case t of
    EmptyNTree => []
  | NTreeNode (n, nts) => n :: (List.concat (List.map flattenNTree nts));

答案 2 :(得分:0)

给出树的类型

datatype 'a tree = Node of 'a * 'a tree list
                 | Leaf

您可以折叠:

fun fold f e0 Leaf = e0
  | fold f e0 (Node (x, ts)) =
    let val e1 = f (x, e0)
    in foldl (fn (t, e2) => fold f e2 t) e1 ts
    end

并将其展平:

fun flatten t =
    fold op:: [] t