11{-# LANGUAGE BangPatterns, CPP, MagicHash, Rank2Types, UnboxedTuples, ScopedTypeVariables #-}
2+ {-# LANGUAGE GeneralizedNewtypeDeriving #-}
23{-# OPTIONS_GHC -fno-full-laziness -funbox-strict-fields #-}
34
45-- | Zero based arrays.
78module Data.HashMap.Array
89 ( Array
910 , MArray
11+ , RunRes (.. )
12+ , RunResA
13+ , RunResM
14+ , Size (.. )
15+ , Sized (.. )
1016
1117 -- * Creation
1218 , new
@@ -25,6 +31,7 @@ module Data.HashMap.Array
2531 , index #
2632 , update
2733 , updateWith'
34+ , updateWithInternal'
2835 , unsafeUpdateM
2936 , insert
3037 , insertM
@@ -36,6 +43,7 @@ module Data.HashMap.Array
3643 , unsafeThaw
3744 , unsafeSameArray
3845 , run
46+ , runInternal
3947 , run2
4048 , copy
4149 , copyM
@@ -317,10 +325,24 @@ unsafeThaw ary
317325 (# s', mary # ) -> (# s', marray mary (length ary) # )
318326{-# INLINE unsafeThaw #-}
319327
328+ -- | Helper datatype used in 'runInternal' and 'updateWithInternal'
329+ data RunRes f e = RunRes {- # UNPACK #-} !Size ! (f e )
330+
331+ type RunResA e = RunRes Array e
332+
333+ type RunResM s e = RunRes (MArray s ) e
334+
320335run :: (forall s . ST s (MArray s e )) -> Array e
321336run act = runST $ act >>= unsafeFreeze
322337{-# INLINE run #-}
323338
339+ runInternal :: (forall s . ST s (RunResM s e )) -> RunResA e
340+ runInternal act = runST $ do
341+ RunRes s mary <- act
342+ ary <- unsafeFreeze mary
343+ return (RunRes s ary)
344+ {-# INLINE runInternal #-}
345+
324346run2 :: (forall s . ST s (MArray s e , a )) -> (Array e , a )
325347run2 k = runST (do
326348 (marr,b) <- k
@@ -392,7 +414,7 @@ updateM ary idx b =
392414 where ! count = length ary
393415{-# INLINE updateM #-}
394416
395- -- | /O(n)/ Update the element at the given positio in this array, by
417+ -- | /O(n)/ Update the element at the given position in this array, by
396418-- applying a function to it. Evaluates the element to WHNF before
397419-- inserting it into the array.
398420updateWith' :: Array e -> Int -> (e -> e ) -> Array e
@@ -401,6 +423,26 @@ updateWith' ary idx f
401423 = update ary idx $! f x
402424{-# INLINE updateWith' #-}
403425
426+ -- | This newtype wrapper is to avoid confusion when local functions
427+ -- take more than one paramenter of 'Int' type (see 'go' in
428+ -- 'Data.HashMap.Base.unionWithKeyInternal').
429+ newtype Size = Size { unSize :: Int }
430+ deriving (Eq , Ord , Num , Integral , Enum , Real )
431+
432+ -- | Helper datatype used in 'updateWithInternal''. Used when a change in
433+ -- a value's size must be returned along with the value itself (typically
434+ -- a hashmap).
435+ data Sized a = Sized {- # UNPACK #-} !Size ! a
436+
437+ -- | /O(n)/ Update the element at the given position in this array, by
438+ -- applying a function to it. Evaluates the element to WHNF before
439+ -- inserting it into the array.
440+ updateWithInternal' :: Array e -> Int -> (e -> Sized e ) -> RunResA e
441+ updateWithInternal' ary idx f =
442+ let Sized sz e = f (index ary idx)
443+ in RunRes sz (update ary idx e)
444+ {-# INLINE updateWithInternal' #-}
445+
404446-- | /O(1)/ Update the element at the given position in this array,
405447-- without copying.
406448unsafeUpdateM :: Array e -> Int -> e -> ST s ()
0 commit comments