module STMContainers.Multimap
(
Multimap,
Association,
Key,
Value,
new,
newIO,
insert,
delete,
deleteByKey,
deleteAll,
lookup,
lookupByKey,
focus,
null,
stream,
streamKeys,
streamByKey,
)
where
import STMContainers.Prelude hiding (insert, delete, lookup, alter, foldM, toList, empty, null)
import qualified Focus
import qualified STMContainers.Map as Map
import qualified STMContainers.Set as Set
newtype Multimap k v = Multimap (Map.Map k (Set.Set v))
deriving (Typeable)
type Association k v = (Key k, Value v)
type Key k = Map.Key k
type Value v = Set.Element v
lookup :: (Association k v) => v -> k -> Multimap k v -> STM Bool
lookup v k (Multimap m) =
maybe (return False) (Set.lookup v) =<< Map.lookup k m
lookupByKey :: Key k => k -> Multimap k v -> STM (Maybe (Set.Set v))
lookupByKey k (Multimap m) = Map.lookup k m
insert :: (Association k v) => v -> k -> Multimap k v -> STM ()
insert v k (Multimap m) =
Map.focus ms k m
where
ms =
\case
Just s ->
do
Set.insert v s
return ((), Focus.Keep)
Nothing ->
do
s <- Set.new
Set.insert v s
return ((), Focus.Replace s)
delete :: (Association k v) => v -> k -> Multimap k v -> STM ()
delete v k (Multimap m) =
Map.focus ms k m
where
ms =
\case
Just s ->
do
Set.delete v s
Set.null s >>= returnDecision . bool Focus.Keep Focus.Remove
Nothing ->
returnDecision Focus.Keep
where
returnDecision c = return ((), c)
deleteByKey :: Key k => k -> Multimap k v -> STM ()
deleteByKey k (Multimap m) =
Map.delete k m
deleteAll :: Multimap k v -> STM ()
deleteAll (Multimap h) = Map.deleteAll h
focus :: (Association k v) => Focus.StrategyM STM () r -> v -> k -> Multimap k v -> STM r
focus =
\s v k (Multimap m) -> Map.focus (liftSetItemStrategy v s) k m
where
liftSetItemStrategy ::
(Set.Element e) => e -> Focus.StrategyM STM () r -> Focus.StrategyM STM (Set.Set e) r
liftSetItemStrategy e s =
\case
Nothing ->
traversePair liftDecision =<< s Nothing
where
liftDecision =
\case
Focus.Replace b ->
do
s <- Set.new
Set.insert e s
return (Focus.Replace s)
_ ->
return Focus.Keep
Just set ->
do
r <- Set.focus s e set
(r,) . bool Focus.Keep Focus.Remove <$> Set.null set
new :: STM (Multimap k v)
new = Multimap <$> Map.new
newIO :: IO (Multimap k v)
newIO = Multimap <$> Map.newIO
null :: Multimap k v -> STM Bool
null (Multimap m) = Map.null m
stream :: Multimap k v -> ListT STM (k, v)
stream (Multimap m) =
Map.stream m >>= \(k, s) -> (k,) <$> Set.stream s
streamKeys :: Multimap k v -> ListT STM k
streamKeys (Multimap m) =
fmap fst $ Map.stream m
streamByKey :: Association k v => k -> Multimap k v -> ListT STM v
streamByKey k (Multimap m) =
lift (Map.lookup k m) >>= maybe mempty Set.stream