{-# LANGUAGE Safe #-}
module Data.GenericTrie
(
Trie
, TrieKey
, empty
, singleton
, fromList
, fromListWith
, fromListWith'
, alter
, insert
, insertWith
, insertWith'
, delete
, at
, member
, notMember
, null
, lookup
, foldWithKey
, fold
, toList
, traverseWithKey
, mapMaybe
, mapMaybeWithKey
, filter
, filterWithKey
, union
, unionWith
, unionWithKey
, intersection
, intersectionWith
, intersectionWithKey
, difference
, differenceWith
, differenceWithKey
, OrdKey(..)
) where
import Control.Applicative (Applicative)
import Data.List (foldl')
import Data.Maybe (isNothing, isJust)
import Prelude hiding (lookup, null, filter)
import Data.GenericTrie.Internal
fromList :: TrieKey k => [(k,v)] -> Trie k v
fromList = foldl' (\acc (k,v) -> insert k v acc) empty
fromListWith :: TrieKey k => (v -> v -> v) -> [(k,v)] -> Trie k v
fromListWith f = foldl' (\acc (k,v) -> insertWith f k v acc) empty
fromListWith' :: TrieKey k => (v -> v -> v) -> [(k,v)] -> Trie k v
fromListWith' f = foldl' (\acc (k,v) -> insertWith' f k v acc) empty
empty :: TrieKey k => Trie k a
empty = trieEmpty
{-# INLINE empty #-}
null :: TrieKey k => Trie k a -> Bool
null = trieNull
{-# INLINE null #-}
lookup :: TrieKey k => k -> Trie k a -> Maybe a
lookup = trieLookup
{-# INLINE lookup #-}
at :: (Functor f, TrieKey k) => k -> (Maybe a -> f (Maybe a)) -> Trie k a -> f (Trie k a)
at k f m = fmap aux (f mv)
where
mv = lookup k m
aux r = case r of
Nothing -> maybe m (const (delete k m)) mv
Just v' -> insert k v' m
insert :: TrieKey k => k -> a -> Trie k a -> Trie k a
insert = trieInsert
{-# INLINE insert #-}
delete :: TrieKey k => k -> Trie k a -> Trie k a
delete = trieDelete
{-# INLINE delete #-}
singleton :: TrieKey k => k -> a -> Trie k a
singleton = trieSingleton
{-# INLINE singleton #-}
mapMaybeWithKey :: TrieKey k => (k -> a -> Maybe b) -> Trie k a -> Trie k b
mapMaybeWithKey = trieMapMaybeWithKey
{-# INLINE mapMaybeWithKey #-}
filter :: TrieKey k => (a -> Bool) -> Trie k a -> Trie k a
filter p = filterWithKey (const p)
filterWithKey :: TrieKey k => (k -> a -> Bool) -> Trie k a -> Trie k a
filterWithKey p = mapMaybeWithKey aux
where
aux k x
| p k x = Just x
| otherwise = Nothing
fold :: TrieKey k => (a -> r -> r) -> r -> Trie k a -> r
fold = trieFoldWithKey . const
{-# INLINE fold #-}
foldWithKey :: TrieKey k => (k -> a -> r -> r) -> r -> Trie k a -> r
foldWithKey = trieFoldWithKey
{-# INLINE foldWithKey #-}
traverseWithKey :: (TrieKey k, Applicative f) => (k -> a -> f b) -> Trie k a -> f (Trie k b)
traverseWithKey = trieTraverseWithKey
{-# INLINE traverseWithKey #-}
mergeWithKey ::
TrieKey k =>
(k -> a -> b -> Maybe c) ->
(Trie k a -> Trie k c) ->
(Trie k b -> Trie k c) ->
Trie k a -> Trie k b -> Trie k c
mergeWithKey = trieMergeWithKey
{-# INLINE mergeWithKey #-}
alter :: TrieKey k => k -> (Maybe a -> Maybe a) -> Trie k a -> Trie k a
alter k f t =
case f (lookup k t) of
Just v' -> insert k v' t
Nothing -> delete k t
insertWith :: TrieKey k => (v -> v -> v) -> k -> v -> Trie k v -> Trie k v
insertWith f k v = alter k $ \mb ->
case mb of
Just v0 -> Just (f v v0)
Nothing -> Just v
insertWith' :: TrieKey k => (v -> v -> v) -> k -> v -> Trie k v -> Trie k v
insertWith' f k v = alter k $ \mb ->
case mb of
Just v0 -> Just $! f v v0
Nothing -> Just v
member :: TrieKey k => k -> Trie k a -> Bool
member k t = isJust (lookup k t)
notMember :: TrieKey k => k -> Trie k a -> Bool
notMember k t = isNothing (lookup k t)
toList :: TrieKey k => Trie k a -> [(k,a)]
toList = foldWithKey (\k v xs -> (k,v) : xs) []
union :: TrieKey k => Trie k a -> Trie k a -> Trie k a
union = mergeWithKey (\_ a _ -> Just a) id id
unionWith :: TrieKey k => (a -> a -> a) -> Trie k a -> Trie k a -> Trie k a
unionWith f = mergeWithKey (\_ a b -> Just (f a b)) id id
unionWithKey :: TrieKey k => (k -> a -> a -> a) -> Trie k a -> Trie k a -> Trie k a
unionWithKey f = mergeWithKey (\k a b -> Just (f k a b)) id id
intersection :: TrieKey k => Trie k a -> Trie k b -> Trie k a
intersection = mergeWithKey (\_ a _ -> Just a) (const empty) (const empty)
intersectionWith :: TrieKey k => (a -> b -> c) -> Trie k a -> Trie k b -> Trie k c
intersectionWith f = mergeWithKey (\_ a b -> Just (f a b)) (const empty) (const empty)
intersectionWithKey :: TrieKey k => (k -> a -> b -> c) -> Trie k a -> Trie k b -> Trie k c
intersectionWithKey f = mergeWithKey (\k a b -> Just (f k a b)) (const empty) (const empty)
difference :: TrieKey k => Trie k a -> Trie k b -> Trie k a
difference = mergeWithKey (\_ _ _ -> Nothing) id (const empty)
differenceWith :: TrieKey k => (a -> b -> Maybe a) -> Trie k a -> Trie k b -> Trie k a
differenceWith f = mergeWithKey (\_ -> f) id (const empty)
differenceWithKey :: TrieKey k => (k -> a -> b -> Maybe a) -> Trie k a -> Trie k b -> Trie k a
differenceWithKey f = mergeWithKey f id (const empty)
mapMaybe :: TrieKey k => (a -> Maybe b) -> Trie k a -> Trie k b
mapMaybe f = mapMaybeWithKey (\_ -> f)