【发布时间】:2019-05-30 23:52:53
【问题描述】:
我发现this Literate Haskell snippet 实现了霍夫曼编码,但我不明白如何使用它。有些函数对我来说是有意义的——例如,我可以这样写:
a = freqList "lol"
build list a
但是我如何计算这个字符串的霍夫曼编码呢? encode 和 encode' 函数似乎采用 Bits 参数。
这是来自 Huffman 编码实现的代码,减去 Literate Haskell cmets:
module Huffman where
import Control.Arrow
import Data.List
import qualified Data.Map as M
import Data.Function
class Eq a => Bits a where
zer :: a
one :: a
instance Bits Int where
zer = 0
one = 1
instance Bits Bool where
zer = False
one = True
type Codemap a = M.Map Char [a]
data HTree = Leaf Char Int
| Fork HTree HTree Int
deriving (Show)
weight :: HTree -> Int
weight (Leaf _ w) = w
weight (Fork _ _ w) = w
merge t1 t2 = Fork t1 t2 (weight t1 + weight t2)
freqList :: String -> [(Char, Int)]
freqList = M.toList . M.fromListWith (+) . map (flip (,) 1)
buildTree :: [(Char, Int)] -> HTree
buildTree = bld . map (uncurry Leaf) . sortBy (compare `on` snd)
where bld (t:[]) = t
bld (a:b:cs) = bld $ insertBy (compare `on` weight) (merge a b) cs
buildCodemap :: Bits a => HTree -> Codemap a
buildCodemap = M.fromList . buildCodelist
where buildCodelist (Leaf c w) = [(c, [])]
buildCodelist (Fork l r w) = map (addBit zer) (buildCodelist l) ++ map (addBit one) (buildCodelist r)
where addBit b = second (b :)
stringTree :: String -> HTree
stringTree = buildTree . freqList
stringCodemap :: Bits a => String -> Codemap a
stringCodemap = buildCodemap . stringTree
encode :: Bits a => Codemap a -> String -> [a]
encode m = concat . map (m M.!)
encode' :: Bits a => HTree -> String -> [a]
encode' t = encode $ buildCodemap t
decode :: Bits a => HTree -> [a] -> String
decode tree = dcd tree
where dcd (Leaf c _) [] = [c]
dcd (Leaf c _) bs = c : dcd tree bs
dcd (Fork l r _) (b:bs) = dcd (if b == zer then l else r) bs
【问题讨论】:
-
仅供参考,
encode和encode'函数没有采用Bits参数;他们要求a(他们返回的列表元素的类型)具有Bits类的实例。有关 Haskell 中的类和实例的更多信息,请参阅 Learn You A Haskell。
标签: haskell huffman-code