SML n 叉树中的非详尽搜索错误
Non exhaustive search error in SML n-ary tree
我正在尝试使用 SML 编写代码并遇到下面列出的问题
我做了一个 N-Ary 树,变量 tr 存储创建的树的值。
val tr =node([leaf "x", node([leaf "y", leaf "x" , leaf "z"])]);
函数 cat 是我希望打印所有叶节点的值的函数。
但是我收到了非详尽搜索警告,但它不起作用。
fun cat (node ( [node t1 , node t2])) = cat(node t1) ^" "^cat(node t2)
| cat ( node ([leaf x, node t1])) = x ^" "^cat(node t1)
| cat( leaf x) = x
这是我的 n 叉树数据结构
datatype
'a ntree = leaf of 'a | node of 'a ntree list;
得到错误如下
`val tr = node [leaf "x",node [leaf "y",leaf "x",leaf "z"]] : string ntree
.\printValues.sml:14.5-16.20 Warning: match nonexhaustive
node (node t1 :: node t2 :: nil) => ...
node (leaf x :: node t1 :: nil) => ...
leaf x => ...
val cat = fn : string ntree -> string
- cat(tr);
uncaught exception Match [nonexhaustive match failure]
raised at: .\printValues.sml:16.20`
`
我该如何解决这个问题?相反,请指出如何继续调试它的方向。
您缺少 cat (node xs)
的定义,其中 xs
的元素少于 2 个。
node
模式只是底层的列表——所以您应该遵循基本的 SML 模式在列表上定义函数,方法是为空列表提供定义,然后为看起来像的模式提供定义x::xs
。在您的情况下,您可能希望单独处理看起来像 node [x]
的模式,以免最后有任何杂散的 space 。以下作品:
fun cat (leaf x) = x
| cat (node []) = ""
| cat (node [x]) = cat x
| cat (node (x::xs)) = cat x ^ " " ^ cat (node xs);
我向上移动了 leaf x
模式——因为对我来说这是一个基础案例,并且按照惯例,基础案例列在最前面。树定义的一个特点是它允许非分支父节点。例如,
node[node[leaf "x"]]
完全有效。 case cat (node [x]) = cat x
的目的是去除那些有些毫无意义的中间节点。最后一个子句中的一个巧妙之处在于,如果 xs
是一个树列表,那么它本身并不是一棵树,因此在被馈送到 cat
之前必须将其包装在 node
构造函数中。
SML 并不完全包括电池 -- 但 Standard ML Basis Library 有一些好东西。有一个 String.concatWith
是一个 join
函数。如果你可以使用它,那么有一种巧妙的方式来写你想要的东西:
fun cat (leaf x) = x
| cat (node branches) = String.concatWith " " (map cat branches);
样本输出:
cat tr;
val it = "x y x z" : string
第一种方法可以被认为是使用硬连线分隔符 (" ") 定义类似 concatWith
的内容,并且在树数据类型中的节点列表的特殊情况下。
我正在尝试使用 SML 编写代码并遇到下面列出的问题 我做了一个 N-Ary 树,变量 tr 存储创建的树的值。
val tr =node([leaf "x", node([leaf "y", leaf "x" , leaf "z"])]);
函数 cat 是我希望打印所有叶节点的值的函数。 但是我收到了非详尽搜索警告,但它不起作用。
fun cat (node ( [node t1 , node t2])) = cat(node t1) ^" "^cat(node t2)
| cat ( node ([leaf x, node t1])) = x ^" "^cat(node t1)
| cat( leaf x) = x
这是我的 n 叉树数据结构
datatype
'a ntree = leaf of 'a | node of 'a ntree list;
得到错误如下
`val tr = node [leaf "x",node [leaf "y",leaf "x",leaf "z"]] : string ntree
.\printValues.sml:14.5-16.20 Warning: match nonexhaustive
node (node t1 :: node t2 :: nil) => ...
node (leaf x :: node t1 :: nil) => ...
leaf x => ...
val cat = fn : string ntree -> string
- cat(tr);
uncaught exception Match [nonexhaustive match failure]
raised at: .\printValues.sml:16.20`
`
我该如何解决这个问题?相反,请指出如何继续调试它的方向。
您缺少 cat (node xs)
的定义,其中 xs
的元素少于 2 个。
node
模式只是底层的列表——所以您应该遵循基本的 SML 模式在列表上定义函数,方法是为空列表提供定义,然后为看起来像的模式提供定义x::xs
。在您的情况下,您可能希望单独处理看起来像 node [x]
的模式,以免最后有任何杂散的 space 。以下作品:
fun cat (leaf x) = x
| cat (node []) = ""
| cat (node [x]) = cat x
| cat (node (x::xs)) = cat x ^ " " ^ cat (node xs);
我向上移动了 leaf x
模式——因为对我来说这是一个基础案例,并且按照惯例,基础案例列在最前面。树定义的一个特点是它允许非分支父节点。例如,
node[node[leaf "x"]]
完全有效。 case cat (node [x]) = cat x
的目的是去除那些有些毫无意义的中间节点。最后一个子句中的一个巧妙之处在于,如果 xs
是一个树列表,那么它本身并不是一棵树,因此在被馈送到 cat
之前必须将其包装在 node
构造函数中。
SML 并不完全包括电池 -- 但 Standard ML Basis Library 有一些好东西。有一个 String.concatWith
是一个 join
函数。如果你可以使用它,那么有一种巧妙的方式来写你想要的东西:
fun cat (leaf x) = x
| cat (node branches) = String.concatWith " " (map cat branches);
样本输出:
cat tr;
val it = "x y x z" : string
第一种方法可以被认为是使用硬连线分隔符 (" ") 定义类似 concatWith
的内容,并且在树数据类型中的节点列表的特殊情况下。