module Data.TrieMap.TrieKey.Buildable (
Buildable(..),
Foldl(..),
mapFoldlKeys,
runFoldl,
defaultUFold,
Distinct,
combineFold) where
import Data.TrieMap.Sized
class Buildable f k | f -> k where
type UStack f :: * -> *
uFold :: Sized a => (a -> a -> a) -> Foldl (UStack f) k a (f a)
type AStack f :: * -> *
aFold :: Sized a => (a -> a -> a) -> Foldl (AStack f) k a (f a)
type DAStack f :: * -> *
daFold :: Sized a => Foldl (DAStack f) k a (f a)
data Foldl stack k a result =
Foldl {snoc :: stack a -> k -> a -> stack a,
begin :: k -> a -> stack a,
zero :: result,
done :: stack a -> result}
instance Functor (Foldl stack k a) where
fmap f Foldl{..} = Foldl{zero = f zero, done = f . done, ..}
runFoldl :: Foldl stack k a result -> [(k, a)] -> result
runFoldl Foldl{..} = fL where
fL [] = zero
fL ((k, a):xs) = fL' (begin k a) xs
fL' !s ((k, a):xs) = fL' (snoc s k a) xs
fL' s [] = done s
mapFoldlKeys :: (k -> k') -> Foldl stack k' a result -> Foldl stack k a result
mapFoldlKeys f Foldl{..} = Foldl{snoc = \ z k a -> snoc z (f k) a, begin = begin . f, ..}
defaultUFold :: f a -> (k -> a -> f a) -> ((a -> a) -> k -> a -> f a -> f a) ->
(a -> a -> a) -> Foldl f k a (f a)
defaultUFold empty single insert f = Foldl{
zero = empty,
begin = single,
snoc = \ m k a -> insert (f a) k a m,
done = id}
data Distinct k z a = Begin k a | Dist k a (z a)
combineFold :: Eq k => Foldl stack k a result -> (a -> a -> a) -> Foldl (Distinct k stack) k a result
combineFold Foldl{..} f = Foldl{snoc = snoc', begin = Begin, zero, done = done'} where
snoc' (Begin k a) k' a'
| k == k' = Begin k (f a' a)
snoc' (Dist k a stk) k' a'
| k == k' = Dist k (f a' a) stk
snoc' stk k a = Dist k a (collapse stk)
done' = done . collapse
collapse (Begin k a) = begin k a
collapse (Dist k a stk) = snoc stk k a