此函数返回的值的含义是什么?您可以使用图表来解释是否需要
data Tree a = Empty_Tree | Node {element :: a, left_tree,right_tree :: Tree a}
gurgle :: Tree a -> Tree a -> Bool
gurgle tree_a tree_b = case (tree_a, tree_b) of
(Empty_Tree , Empty_Tree ) -> True
(Empty_Tree , _ ) -> False
(_ , Empty_Tree ) -> False
(Node _ left_a right_a, Node _ left_b right_b) -> gurgle left_a right_b
&& gurgle right_a left_b
答案 0 :(得分:6)
让我们画出来。首先,我将在空树上使用小圆圈,在节点上使用圆圈表示数据,并为子树使用两个分支。 left
和right
本身也是树木。
好的,让我们逐行获取代码并将case语句解压缩到顶层的模式匹配中,因为
function x y = case (x,y) of
(0,1) -> this
(1,10) -> that
可以写
function 0 1 = this
function 1 10 = that
在这里学到很多东西 - 如果它们都是空的那就是肯定的。行。
这意味着我们得到像
这样的东西
因为无论第二个参数是什么,它都会给出False
。我们已经消除了第二个参数在最后一行是Empty_Tree
的情况,所以第二个参数必须是非空的,在这里给出False。
下一行非常喜欢它,只是相反:
再次,像这样的东西
得到一个否定答案。我开始怀疑,一旦我读完这两行,它就会检查两棵树的形状是否相同。
这是最有趣的一个。注意它正在做的交换方面的事情。它不只是检查两者的子树是否相同,而是从右侧与左侧进行比较。
还要注意它忽略了节点的值 - 这就是为什么我在这个例子中删除了数字。
为了使其真实,我们需要一个左边的形状以匹配另一个右边的形状:
递归案例说,一个人的左边必须与另一个人的右边相匹配。当你忽略这些值时,树必须是彼此的镜像。
原文中的递归案例
(Node _ left_a right_a, Node _ left_b right_b) -> gurgle left_a right_b
&& gurgle right_a left_b
让我们为该代码着色以匹配上图:
将其着色是一个很好的视觉线索,因为左边的名称left_a
等并不意味着什么特别的,它们只是指向树的位。
哪些位?
这与Node的定义相符:
第一个(灰色)位是元素。 element
现在是从树节点到值的函数。
第二个(浅棕色)位是左子树left_tree
。它可能很大而且复杂,或只是Empty_Tree
。 (它可以是任何树。)
第三个(淡橙色)位是正确的子树right_tree
。它们与我的图表匹配:
我没有在彩色框中添加任何细节 - 它可以是任何树,无论大小。
当您的原始代码将其放在左侧时
它为子树命名,以便它可以直接引用它们,而不是使用left-tree
和right_tree
函数。