Haskell函数寻求解释

Haskell函数寻求解释,haskell,functional-programming,binary-tree,Haskell,Functional Programming,Binary Tree,有人能解释一下Haskell函数吗 标签::B树a->[a] 反射::B树a->B树a 第一:一些格式。在Haskell中,此代码通常是这样格式化的: 数据树a=空 |节点B树a树a树a 标签::B树a->[a] 标签为空=[] 标签节点左标签右=标签左+++[label]++labels右 反射::B树a->B树a 反射空=空 反射节点左标签右=节点反射左标签反射右 提示:如果将代码缩进4个空格,它将正确显示并突出显示语法。 现在让我们看一下: 数据树a=空 |节点B树a树a树a 定义新的“参

有人能解释一下Haskell函数吗

标签::B树a->[a]

反射::B树a->B树a


第一:一些格式。在Haskell中,此代码通常是这样格式化的:

数据树a=空 |节点B树a树a树a 标签::B树a->[a] 标签为空=[] 标签节点左标签右=标签左+++[label]++labels右 反射::B树a->B树a 反射空=空 反射节点左标签右=节点反射左标签反射右 提示:如果将代码缩进4个空格,它将正确显示并突出显示语法。 现在让我们看一下:

数据树a=空 |节点B树a树a树a 定义新的“参数化”数据类型。它被称为参数化,因为它是一个小的类型参数。这意味着可以用任何其他类型替换,例如Int、Double、String或其他类型。在C++中或java中的泛型中思考模板。Empty和Node称为数据类型的构造函数。BTree A可以是空的,也可以是|所表示的包含一个包含BTree A和另一个BTree A的节点。该定义是递归的,因为数据类型BTree a显示在其自己的定义中

标签::B树a->[a] 标签为空=[] 标签节点左标签右=标签左+++[label]++labels右 标签收集树中包含的所有值。第一行是类型声明:它接受一个具有节点BTree a的二叉树,并将其映射到as[a]的列表。单是这个类型就已经让你对可能发生的事情有了一个很好的了解

接下来的两行是所谓的模式匹配。这些类似于其他语言中的case语句:您可以区分不同的可能性,然后选择适当的case,尽管它们的功能更强大。您应该注意到它们是如何精确地对应于btreea拥有的两个构造函数的。如果我们在一个空节点上,那么我们将返回一个空列表[]。否则,我们将进入下一行,并有一个节点,该节点必须有一个BTree a和一个BTree a,我们将其绑定到left、label和right。我们可能会称之为left、label和right,但这些都是直观的

现在左和右又是bTreeA类型,因此我们可以调用这两个类型的标签,并期望它们返回as列表,即[a]。所以标签也是递归的,因为它在定义中调用自己。这是一种非常强大的技术,在Haskell中被大量使用。标签然后连接从标签左侧获得的列表,其中仅包含当前标签[label],然后连接从标签右侧获得的列表。因此,我们可以有效地得出结论,它将左子树中的标签与当前标签以及右子树中的标签连接起来,并将其全部放入一个列表中

反射::B树a->B树a 反射空=空 反射节点左标签右=节点反射左标签反射右
其工作方式和标签基本相同,只是它返回标签树而不是列表。所以实际上,这没有任何作用,这是一个昂贵的身份函数。但它是更强大的东西的模板。例如,您可以很容易地传递另一个函数来反映它并将其应用于它的每个元素

你认为他们是干什么的?当你在一个小的示例树上运行它们时会发生什么?-1:听无用的人说什么。在提出问题之前,请展示你在问题背后的一些思考过程。如果你努力思考答案,你会学到更多。如果您不这样做,那么您将错过编程中的许多乐趣。我认为反射的第二个等式应该是反射节点left label right=节点反射右label reflect left,并且操作被错误复制。
data BTree a = Empty | Node (BTree a) a (BTree a) -- This is a node-labelled binary tree
labels Empty = []
labels (Node left label right) = labels left ++ [label] ++ labels right
reflect Empty = Empty
reflect (Node left label right) = Node (reflect left) label (reflect right)