on develop help sign in
reflex/src/Data/FastMutableIntMap.hs
97 lines 3.2 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 , toList
25 ) where
27--TODO: Pure JS version
28--TODO: Fast copy to FastIntMap
29--TODO: Fast patch type
31import Prelude hiding (lookup)
33import Control.Monad.IO.Class
34import Data.Foldable (traverse_)
35import Data.IntMap.Strict (IntMap)
36import qualified Data.IntMap.Strict as IntMap
37import Data.IORef
38import Data.Patch.Class
39import Data.Patch.IntMap
41-- | A 'FastMutableIntMap' holds a map of values of type @a@ and allows low-overhead modifications via IO.
42-- Operations on 'FastMutableIntMap' run in IO.
43newtype FastMutableIntMap a = FastMutableIntMap (IORef (IntMap a))
45-- | Create a new 'FastMutableIntMap' out of an 'IntMap'
46new :: IntMap a -> IO (FastMutableIntMap a)
47new m = FastMutableIntMap <$> newIORef m
49-- | Create a new empty 'FastMutableIntMap'
50newEmpty :: IO (FastMutableIntMap a)
51newEmpty = FastMutableIntMap <$> newIORef IntMap.empty
53-- | Insert an element into a 'FastMutableIntMap' at the given key
54insert :: FastMutableIntMap a -> Int -> a -> IO ()
55insert (FastMutableIntMap r) k v = modifyIORef' r $ IntMap.insert k v
57-- | Attempt to lookup an element by key in a 'FastMutableIntMap'
58lookup :: FastMutableIntMap a -> Int -> IO (Maybe a)
59lookup (FastMutableIntMap r) k = IntMap.lookup k <$> readIORef r
61-- | Runs the provided action over the intersection of a 'FastMutableIntMap' and an 'IntMap'
62forIntersectionWithImmutable_ :: MonadIO m => FastMutableIntMap a -> IntMap b -> (a -> b -> m ()) -> m ()
63forIntersectionWithImmutable_ (FastMutableIntMap r) b f = do
64 a <- liftIO $ readIORef r
65 traverse_ (uncurry f) $ IntMap.intersectionWith (,) a b
67-- | Runs the provided action over the values of a 'FastMutableIntMap'
68for_ :: MonadIO m => FastMutableIntMap a -> (a -> m ()) -> m ()
69for_ (FastMutableIntMap r) f = do
70 a <- liftIO $ readIORef r
71 traverse_ f a
73-- | Checks whether a 'FastMutableIntMap' is empty
74isEmpty :: FastMutableIntMap a -> IO Bool
75isEmpty (FastMutableIntMap r) = IntMap.null <$> readIORef r
77-- | Retrieves the size of a 'FastMutableIntMap'
78size :: FastMutableIntMap a -> IO Int
79size (FastMutableIntMap r) = IntMap.size <$> readIORef r
81-- | Make an immutable snapshot of the datastructure and clear it
82getFrozenAndClear :: FastMutableIntMap a -> IO (IntMap a)
83getFrozenAndClear (FastMutableIntMap r) = do
84 result <- readIORef r
85 writeIORef r IntMap.empty
86 return result
88-- | Updates the value of a 'FastMutableIntMap' with the given patch (see 'Data.Patch.IntMap'),
89-- and returns an 'IntMap' with the modified keys and values.
90applyPatch :: FastMutableIntMap a -> PatchIntMap a -> IO (IntMap a)
91applyPatch (FastMutableIntMap r) p@(PatchIntMap m) = do
92 v <- readIORef r
93 writeIORef r $! applyAlways p v
94 return $ IntMap.intersection v m
96toList :: FastMutableIntMap a -> IO [(Int, a)]
97toList (FastMutableIntMap r) = IntMap.toList <$> readIORef r