cedict-0.2.1: Data/Char/CEDICT/Reader/RoseBush.hs
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE OverlappingInstances #-}
{-# LANGUAGE FlexibleInstances #-}
module Data.Char.CEDICT.Reader.RoseBush
( readyToSerialize
) where
import Data.Char.CEDICT.Reader.ListRebuild
import Control.Arrow
import Data.Maybe
import Data.List
import Data.Ord
readyToSerialize ::
DictList -> ([(Int, [(Char, Int)])], [[(String, String)]])
readyToSerialize = packForConversion . map lenBush . part
data (Ord k) => RoseBush k v
= Bud k v
| Blossom k v [RoseBush k v]
| Petals k [RoseBush k v]
key rose =
case rose of
Bud k _ -> k
Blossom k _ _ -> k
Petals k _ -> k
instance (Ord k, Show k, Show v) => Show (RoseBush k v) where
show bush = show' 0 show bush
instance (Show v) => Show (RoseBush Char v) where
show bush = show' 0 passChar bush
where
passChar c = [c]
show' ::
(Ord k, Show k, Show v) => Int -> (k -> String) -> RoseBush k v -> String
show' i kHandler bush =
case bush of
Bud k v -> ws $ unwords [kHandler k, ":", show v]
Blossom k v roses ->
(ws $ unwords [kHandler k, ":", show v]) ++ (recurse roses)
Petals k roses ->
(ws $ kHandler k) ++ (recurse roses)
where
ws = ((replicate i ' ') ++) . (++ "\n")
recurse = concat . map (show' (i + 2) kHandler)
part [] = []
part (([ ], v):rest) = part rest
part ((k:s, v):rest) = leader : (part outer)
where
(inner, outer) = part' k rest
leader =
if null s then
if null inner then
Bud k v
else
Blossom k v $ part $ pop inner
else
Petals k $ part $ (s, v):(pop inner)
part' k = partition ((== k) . head . fst) . nonNulls
pop = nonNulls . map (first tail)
nonNulls = filter $ not . null . fst
lenBush rose =
case rose of
Bud k v -> Bud k (Just v, len)
Blossom k v roses -> Blossom k (Just v, len) $ lenBush' roses
Petals k roses -> Blossom k (Nothing, len) $ lenBush' roses
where
len = lenSubList rose
lenBush' = map $ lenBush
linearize lists keys = (1 * lists) + (2 * keys)
serialize roses = top : recurse
where
top = serialize' (1, length roses) roses
recurse = concatMap serialize $ pullUp roses
pullUp [] = []
pullUp (h:t) =
case h of
Blossom _ _ roses -> roses : (pullUp t)
Bud _ _ -> pullUp t
Petals _ _ -> pullUp t
serialize' _ [] = []
serialize' o (h:t) =
case h of
Blossom k (v, o') _ -> (Bud k (v, o)) : (serialize' (sumX o o') t)
Bud k (v, _) -> h : (serialize' o t)
Petals _ _ -> serialize' o t
packForConversion roses = (searchList, pinDefList)
where
seared = serialize roses
searchList = map (length &&& (map pullO)) seared
pinDefList = concatMap (c' . (vals &&& spacers)) seared
where
spacers = flip replicate [] . length
vals = map pullV
c' = ([] :) . uncurry (++)
pullO (Bud k (_, o)) = (k, uncurry linearize $ o)
pullO (Blossom k (_, o) _) = (k, uncurry linearize $ o)
pullV rose =
case rose of
Bud k (Just v, _) -> v
Blossom k (Just v, _) _ -> v
_ -> []
lenSubList :: (Ord k) => RoseBush k v -> (Int, Int)
lenSubList rose =
case rose of
Bud _ _ -> (0, 0)
Blossom _ _ roses -> recurse roses
Petals _ roses -> recurse roses
recurse roses = foldl sumX (1, length roses) (map lenSubList roses)
sumX (a, b) (a', b') = (a + a', b + b')
samples = sort
[ "modes"
, "cats"
, "ca"
, "a"
, "letters"
, "latrine"
, "moses"
, "mosey"
, "axiom"
]