【问题标题】:how to traverse a tree structure and change its data type如何遍历树结构并更改其数据类型
【发布时间】:2019-02-08 11:41:16
【问题描述】:

我正在尝试在 haskell 中实现霍夫曼编码并使用以下两种数据结构:

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 的 Integer 部分。

【问题讨论】:

  • 而且我认为最后一行的分组不正确,即使意图很明确:试试Branch (createHtree w1) (createHtree w2)
  • 哇,我不敢相信这行得通,它现在编译了。我感到很茫然
  • Branch createHtree(w1) createHtree(w2)Branch createHtree w1 createHtree w2 相同,后者使用四个参数调用构造函数Branch(触发错误)。 Haskell 中的召回函数应用是 (f x) 而不是 f(x)
  • 确实,这些是完全不同的。例如f x y 使用参数xy 调用函数f。它相当于(f x) y。相反,f (x y) 将调用函数f,只使用一个参数,即调用函数x 和参数y 的结果。因此,应该小心使用括号。
  • 是的,表达式=的右边,patterns在左边!在 RHS 上 (L w char) 构造 a 值(从两个值),在 LHS 上它解构这样的值。

标签: haskell type-conversion binary-tree huffman-code


【解决方案1】:

您可以通过仅使用一种数据类型并通过您希望在每个节点存储的数据类型对其进行参数化来简化此任务:

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 = (() <$)

请注意,现在 stripLabels 非常简单,您甚至不需要定义它:您可以在使用站点内联它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-26
    • 2022-01-22
    • 2015-06-30
    • 2018-12-27
    相关资源
    最近更新 更多