{-# LANGUAGE TemplateHaskell #-} module SimpleTrie where import qualified Data.Map.Strict as M import Control.Lens data Trie a b = Trie { _trieMVal :: Maybe b , _trieChildren :: M.Map a (Trie a b) } makeLenses ''Trie emptyTrie :: Trie a b emptyTrie = Trie Nothing M.empty singletonTrie :: Ord a => [a] -> b -> Trie a b singletonTrie (k:ks) x = Trie Nothing $ M.singleton k $ singletonTrie ks x singletonTrie [] x = Trie (Just x) M.empty insertInTrie :: Ord a => [a] -> b -> Trie a b -> Trie a b insertInTrie [] x = trieMVal ?~ x insertInTrie (k:ks) x = trieChildren %~ M.insertWith f k (singletonTrie ks x) where f _ = insertInTrie ks x lookupTrie :: Ord a => [a] -> Trie a b -> Maybe b lookupTrie (k:ks) t = _trieChildren t M.!? k >>= lookupTrie ks lookupTrie [] t = _trieMVal t multiLookupTrie :: Ord a => [a] -> Trie a b -> [([a],b)] multiLookupTrie xs t@(Trie my ch) | null xs || null ch = maybe [] (\y -> [([],y)]) my | otherwise = let (z:zs) = xs in case M.lookup z ch of Nothing -> multiLookupTrie zs t Just t' -> map (_1 %~ (z:)) (multiLookupTrie zs t') ++ multiLookupTrie zs t multiLookupTrieI :: Ord a => [(a,c)] -> Trie a b -> [([c],b)] multiLookupTrieI xs t@(Trie my ch) | null xs || null ch = maybe [] (\y -> [([],y)]) my | otherwise = let ((z1,z2):zs) = xs in case M.lookup z1 ch of Nothing -> multiLookupTrieI zs t Just t' -> map (_1 %~ (z2:)) (multiLookupTrieI zs t') ++ multiLookupTrieI zs t