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

Functional programming 如何从数据类型中提取元组?,functional-programming,sml,Functional Programming,Sml,熟悉SML,并尝试通过一系列练习进行学习。我试图写的函数是关于用N个孩子压平一棵树。我的方法是简单地获取当前的NTreeNode,并将其值添加到我将返回的某个列表中。然后接受它的第二个参数,孩子的列表,并将其附加到另一个列表上,这将是我的队列。这个队列将作为我仍然要处理的所有项目 我试图通过将NTreeList和我将返回的列表以及flattentree中的初始值传递给一个helper函数来实现这种方法 但是,当我试图处理队列中的NTreeNode时,它会返回一个NTree,并且我不能对其使用第一

熟悉SML,并尝试通过一系列练习进行学习。我试图写的函数是关于用N个孩子压平一棵树。我的方法是简单地获取当前的
NTreeNode
,并将其值添加到我将返回的某个列表中。然后接受它的第二个参数,孩子的列表,并将其附加到另一个列表上,这将是我的队列。这个队列将作为我仍然要处理的所有项目

我试图通过将
NTreeList
和我将返回的列表以及
flattentree
中的初始值传递给一个helper函数来实现这种方法

但是,当我试图处理队列中的
NTreeNode
时,它会返回一个
NTree
,并且我不能对其使用
第一个
/
第二个
函数,我需要从队列中返回一个元组。我只是不知道如何取回元组,我尝试使用
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])
    ])
  ]);

您的
processTree
函数缺少
EmptyNTree
的情况,您似乎试图在调用
first
second
之前添加
NTree
构造函数,而您需要像在
flattentree
中那样将它们去掉

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

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])
;

您也可以考虑基于列表函数的实现(虽然结果的顺序不一样):


使用模式匹配来分解东西要比摆弄诸如
first
tl
之类的选择器容易得多

相反地累积一个列表并在完成时修复它也比重复地追加到列表末尾更有效

fun processTree [] final = reverse final
  | processTree (EmptyTree::ts) final = processTree ts final
  | processTree ((NTreeNode (v,t))::ts) final = processTree (ts @ t) (v :: final)
给定树类型

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
fun flatten t =
    fold op:: [] t