Что ж, похоже, вы на правильном пути.
возвращает только первый символ в дереве.
Ваша главная проблема с этими двумя строками:
traT (Leaf v) c bs res= (res++[v], True)
...
traT _ c bs res = traT c c (bs) res
Первый маскирует второй для всех конечных узлов. И второй - ваш единственный прямой рекурсивный вызов, который может работать на конечных узлах, следовательно, ваша единственная надежда - обработать любые последующие биты.
Пара замечаний:
- выражение
res++[v]
заставляет код повторно сканировать весь список символов при каждом новом символе. - Вторая строка будет вызывать себя бесконечно (но она маскируется первой).
Другая (меньшая) проблема заключается в том, что возвращение только одного флага на наличие «лишних» битов в конце потока битов приводит к потере информации, поскольку мы хотели бы знать, что такое дополнительные биты. Это немного рискованно делать в вашей основной рекурсивной функции. Конечно, вполне нормально делать это в финальной внешней функции decode
.
Вот почему в приведенном ниже примере кода я использовал дополнительный аргумент symBits
, чтобы сохранить биты, которые былиобработано, но еще не приписано к символу. Я храню их в обратном порядке, потому что Haskell предпочитает добавлять элементы в список, а не помещать их в конец, повторно сканируя весь список, чтобы сделать это. Отсюда и вызов reverse
на финальной стадии обработки. Это дешевый reverse
вызов, так как он ограничен по длине до глубины нашего дерева Хаффмана.
Итак, вот несколько предложенных переработанных кодов, в которых я попытался выделить 4 случая: листовой узел илиУзел форка И в конце потока битов или нет. Я также позволил себе переименовать ваш c
аргумент в htop.
data BTree a = Leaf a | Fork (BTree a) (BTree a) deriving (Show, Eq)
type Bit = Bool
-- hnode htop symBits bs
travHT :: BTree a -> BTree a -> [Bit] -> [Bit] -> ([a], [Bit])
-- situations where at least one input bit remains:
travHT (Leaf v) htop symBits (b:rbs) = -- CHANGE: forward recursive call
-- symbol completed, jump from leaf node to top of htree:
let fwdRes = travHT htop htop [] (b:rbs)
nextSyms = fst fwdRes
lastSymBits = snd fwdRes
in (v : nextSyms, lastSymBits)
travHT (Fork left right) htop symBits (b:rbs)
| b = travHT right htop (b:symBits) rbs
| otherwise = travHT left htop (b:symBits) rbs
-- situations where we have reached the end of the bit stream:
travHT (Leaf v) htop symBits [] = ([v],[])
-- no more bits and not at a leaf --> incomplete last symbol:
travHT (Fork left right) htop symBits [] = ([], reverse symBits)
-- homework-mandated interface:
decode :: BTree a -> [Bit] -> ([a], Bool)
decode htree bs =
let pair = travHT htree htree [] bs
(symbols, restOfBits) = pair
weUsedAllBits = null restOfBits
in (symbols, weUsedAllBits)
Тестирование кода с помощью основной программы токена:
xyz_code :: BTree Char
xyz_code = Fork (Leaf 'x') (Fork (Leaf 'y') (Leaf 'z'))
-- Bit streams for test purposes:
------ Y Z X X X Y/Z??
bl0 = [True,False, True,True , False, False, False]
bl1 = [True,False, True,True , False, False, False, True]
main = do
let bitList = bl0
let htree = xyz_code
let result = decode htree bitList
putStrLn $ "result = " ++ show result
Вывод программы:
result = ("yzxxx",True)
Надеюсь, это поможет. Я также попрошу у полномочий, которые будут , добавить тег [huffman-code] к вашему вопросу. Теги - это хороший способ помочь людям найти интересующие их вопросы. И у нас есть тег для кодов Хаффмана.