Haskell 树声明之间的区别?
两者之间有什么区别Haskell 树声明之间的区别?,haskell,Haskell,两者之间有什么区别 data Tree a = Leaf a | Node (a, Tree a, Tree a) deriving Show 及 注意:节点的括号有一个区别:在第一个括号中,节点是一个构造函数,有一个字段,一个元组。这意味着,当我们给它一个类型时,它的形式是节点::(a,treea,treea)->treea,一个直接指向树的函数。后者是一个具有3个字段的构造函数,因此该构造函数使用适当的curried函数类型化 现在看来,这两个声明是等价的,但在这两个声明中有多少间接性存在
data Tree a = Leaf a | Node (a, Tree a, Tree a) deriving Show
及
注意:节点的括号有一个区别:在第一个括号中,节点是一个构造函数,有一个字段,一个元组。这意味着,当我们给它一个类型时,它的形式是
节点::(a,treea,treea)->treea
,一个直接指向树的函数。后者是一个具有3个字段的构造函数,因此该构造函数使用适当的curried函数类型化
现在看来,这两个声明是等价的,但在这两个声明中有多少间接性存在着显著差异。在第一个例子中,我们有一个指向三个指针组成的元组的指针。在第二个例子中,构造函数中直接有3个指针。这可能会对效率产生一些影响(间接寻址总是这样),并且还会在第一个定义中引入一个额外的值,节点未定义
(或者更一般地说,节点124;
),后者没有明确的等价物
这是因为Haskell中的每一级间接性都让我们能够构造一个新的时髦的伪值,其中最外层的包装器求值,但间接性(提供惰性)指向一个不同的thunk。如果你用一种严格的语言来观察它们,你会发现它们是同构的,但严格地说,它们在Haskell模型中应该有不同的表示
对于惯用且更高效的代码,请选择后者。另外请注意,节点(树a)a(树a)
如果按顺序遍历该树特别有意义(例如,对于搜索树),则会比这两者都好,因为这将允许您使用派生(可折叠、可遍历)
,并获得您可能想要的结果。
data Tree a = Leaf a | Node a (Tree a) (Tree a) deriving Show