on add-notready-instances help sign in
reflex/src/Data/FastMutableIntMap.hs
93 lines 3.1 kB history raw
1{-# LANGUAGE TypeFamilies #-}
2-- |
3-- Module:
4-- Data.FastMutableIntMap
5-- Description:
6-- A mutable version of 'IntMap'
7module Data.FastMutableIntMap
8 ( FastMutableIntMap
9 , new
10 , newEmpty
11 , insert
12 , isEmpty
13 , getFrozenAndClear
14 , size
15 , applyPatch
16 , PatchIntMap (..)
17 , traverseIntMapPatchWithKey
18 , lookup
19 , forIntersectionWithImmutable_
20 , for_
21 , patchIntMapNewElements
22 , patchIntMapNewElementsMap
23 , getDeletions
24 ) where
26--TODO: Pure JS version
27--TODO: Fast copy to FastIntMap
28--TODO: Fast patch type
30import Prelude hiding (lookup)
32import Control.Monad.IO.Class
33import Data.Foldable (traverse_)
34import Data.IntMap.Strict (IntMap)
35import qualified Data.IntMap.Strict as IntMap
36import Data.IORef
37import Reflex.Patch.Class
38import Reflex.Patch.IntMap
40-- | A 'FastMutableIntMap' holds a map of values of type @a@ and allows low-overhead modifications via IO.
41-- Operations on 'FastMutableIntMap' run in IO.
42newtype FastMutableIntMap a = FastMutableIntMap (IORef (IntMap a))
44-- | Create a new 'FastMutableIntMap' out of an 'IntMap'
45new :: IntMap a -> IO (FastMutableIntMap a)
46new m = FastMutableIntMap <$> newIORef m
48-- | Create a new empty 'FastMutableIntMap'
49newEmpty :: IO (FastMutableIntMap a)
50newEmpty = FastMutableIntMap <$> newIORef IntMap.empty
52-- | Insert an element into a 'FastMutableIntMap' at the given key
53insert :: FastMutableIntMap a -> Int -> a -> IO ()
54insert (FastMutableIntMap r) k v = modifyIORef' r $ IntMap.insert k v
56-- | Attempt to lookup an element by key in a 'FastMutableIntMap'
57lookup :: FastMutableIntMap a -> Int -> IO (Maybe a)
58lookup (FastMutableIntMap r) k = IntMap.lookup k <$> readIORef r
60-- | Runs the provided action over the intersection of a 'FastMutableIntMap' and an 'IntMap'
61forIntersectionWithImmutable_ :: MonadIO m => FastMutableIntMap a -> IntMap b -> (a -> b -> m ()) -> m ()
62forIntersectionWithImmutable_ (FastMutableIntMap r) b f = do
63 a <- liftIO $ readIORef r
64 traverse_ (uncurry f) $ IntMap.intersectionWith (,) a b
66-- | Runs the provided action over the values of a 'FastMutableIntMap'
67for_ :: MonadIO m => FastMutableIntMap a -> (a -> m ()) -> m ()
68for_ (FastMutableIntMap r) f = do
69 a <- liftIO $ readIORef r
70 traverse_ f a
72-- | Checks whether a 'FastMutableIntMap' is empty
73isEmpty :: FastMutableIntMap a -> IO Bool
74isEmpty (FastMutableIntMap r) = IntMap.null <$> readIORef r
76-- | Retrieves the size of a 'FastMutableIntMap'
77size :: FastMutableIntMap a -> IO Int
78size (FastMutableIntMap r) = IntMap.size <$> readIORef r
80-- | Make an immutable snapshot of the datastructure and clear it
81getFrozenAndClear :: FastMutableIntMap a -> IO (IntMap a)
82getFrozenAndClear (FastMutableIntMap r) = do
83 result <- readIORef r
84 writeIORef r IntMap.empty
85 return result
87-- | Updates the value of a 'FastMutableIntMap' with the given patch (see 'Reflex.Patch.IntMap'),
88-- and returns an 'IntMap' with the modified keys and values.
89applyPatch :: FastMutableIntMap a -> PatchIntMap a -> IO (IntMap a)
90applyPatch (FastMutableIntMap r) p@(PatchIntMap m) = do
91 v <- readIORef r
92 writeIORef r $! applyAlways p v
93 return $ IntMap.intersection v m