Haskell 如何遍历树结构并更改其数据类型
我试图在haskell中实现huffman编码,并使用以下两种数据结构:Haskell 如何遍历树结构并更改其数据类型,haskell,type-conversion,binary-tree,huffman-code,Haskell,Type Conversion,Binary Tree,Huffman Code,我试图在haskell中实现huffman编码,并使用以下两种数据结构: data Htree = Leaf Char | Branch Htree Htree deriving Show data Wtree = L Integer Char | B Integer Wtree Wtree deriving Show 其中Wtree首先基于每个字符的频率/权重创建。 在构建Wtree之后,我们知道树的结构,我不再需要每个叶/枝的权重,所以我想将Wtree转换为Htree,但我在解决这个问题时
data Htree = Leaf Char | Branch Htree Htree deriving Show
data Wtree = L Integer Char | B Integer Wtree Wtree deriving Show
其中Wtree首先基于每个字符的频率/权重创建。
在构建Wtree之后,我们知道树的结构,我不再需要每个叶/枝的权重,所以我想将Wtree转换为Htree,但我在解决这个问题时遇到了困难
createHtree :: Wtree -> Htree
createHtree(L _ char) = Leaf char
createHtree(B _ w1 w2) = Branch createHtree(w1) createHtree(w2)
这是我尝试的解决方案,但无法编译
正如我提到的,预期的结果是从Wtree到Htree的转换,只需要删除Wtree的整数部分。您可以通过仅使用单个数据类型,并根据希望存储在每个节点上的数据类型对其进行参数化,从而简化此任务:
data HTree a = Leaf a Char | Branch a (HTree a) (HTree a)
然后,加权树是HTree Integer
,而未加权树是HTree()
,表示不希望在树中存储额外数据。通过这种方式,Haskell可以清楚地看到,您的两种类型是密切相关的——根据您在问题中发布的代码,它们似乎是两种完全不相关的类型。如果您另外启用了一个无害的语言扩展,那么您可以使用这种密切的关系来避免自己编写转换
{-# LANGUAGE DeriveFunctor #-}
import Data.Functor ((<$))
data HTree a = Leaf a Char
| Branch a (HTree a) (HTree a)
deriving Functor
stripLabels :: HTree a -> HTree ()
stripLabels = (() <$)
{-#语言派生函子#-}
导入数据。函子((HTree()
stripLabels=(()您可以通过只使用一种数据类型,并根据希望存储在每个节点上的数据类型对其进行参数化来简化此任务:
data HTree a = Leaf a Char | Branch a (HTree a) (HTree a)
然后,加权树是HTree Integer
,而未加权树是HTree()
,表示您不希望在树中存储额外的数据。这样,Haskell可以清楚地看到您的两种类型是密切相关的-对于您在问题中发布的代码,它们似乎是两种完全不相关的类型。如果您另外启用一种无害的语言扩展,您可以使用这种密切关系来避免编写你自己的转变
{-# LANGUAGE DeriveFunctor #-}
import Data.Functor ((<$))
data HTree a = Leaf a Char
| Branch a (HTree a) (HTree a)
deriving Functor
stripLabels :: HTree a -> HTree ()
stripLabels = (() <$)
{-#语言派生函子#-}
导入数据。函子((HTree()
stripLabels=(())我认为最后一行没有正确分组,尽管意图很清楚:试试Branch(createHtree w1)(createHtree w2)
wow我不敢相信这是有效的,它现在已经编译了。我感到目瞪口呆Branch createHtree(w1)createHtree(w2)
与Branch createHtree w1 createHtree w2
相同,后者使用四个参数调用构造函数Branch
(触发错误)。Haskell中的调用函数应用程序是(f x)
而不是f(x)
。事实上,这两种方法完全不同。例如fxy
使用参数x
和y
调用函数f
。它相当于(fx)y
。相反,f(xy)
将只使用一个参数调用函数f
,使用参数y
调用函数x
的结果。因此,使用括号时要小心。是的,=
右侧的表达式,左侧的模式!在RHS(L w char)
上构造了一个值(来自两个值),在LHS上,它解构了这样一个值。我认为最后一行没有正确分组,尽管意图很清楚:试试Branch(createHtree w1)(createHtree w2)
wow我不敢相信这是有效的,它现在编译了。我感到目瞪口呆Branch createHtree(w1)createHtree(w2)
与Branch createHtree w1 createHtree w2
相同,后者使用四个参数调用构造函数Branch
(触发错误)。Haskell中的调用函数应用程序是(f x)
而不是f(x)
。事实上,这两种方法完全不同。例如fxy
使用参数x
和y
调用函数f
。它相当于(fx)y
。相反,f(xy)
将只使用一个参数调用函数f
,使用参数y
调用函数x
的结果。因此,使用括号时要小心。是的,=
右侧的表达式,左侧的模式!在RHS(L w char)
上构造了一个值(来自两个值)在LHS上,它解构了这样一个值。