1
1
{-# LANGUAGE BangPatterns, CPP, MagicHash, Rank2Types, UnboxedTuples, ScopedTypeVariables #-}
2
+ {-# LANGUAGE GeneralizedNewtypeDeriving #-}
2
3
{-# OPTIONS_GHC -fno-full-laziness -funbox-strict-fields #-}
3
4
4
5
-- | Zero based arrays.
7
8
module Data.HashMap.Array
8
9
( Array
9
10
, MArray
11
+ , RunRes (.. )
12
+ , RunResA
13
+ , RunResM
14
+ , Size (.. )
15
+ , Sized (.. )
10
16
11
17
-- * Creation
12
18
, new
@@ -25,6 +31,7 @@ module Data.HashMap.Array
25
31
, index #
26
32
, update
27
33
, updateWith'
34
+ , updateWithInternal'
28
35
, unsafeUpdateM
29
36
, insert
30
37
, insertM
@@ -36,6 +43,7 @@ module Data.HashMap.Array
36
43
, unsafeThaw
37
44
, unsafeSameArray
38
45
, run
46
+ , runInternal
39
47
, run2
40
48
, copy
41
49
, copyM
@@ -313,10 +321,24 @@ unsafeThaw ary
313
321
(# s', mary # ) -> (# s', marray mary (length ary) # )
314
322
{-# INLINE unsafeThaw #-}
315
323
324
+ -- | Helper datatype used in 'runInternal' and 'updateWithInternal'
325
+ data RunRes f e = RunRes {- # UNPACK #-} !Size ! (f e )
326
+
327
+ type RunResA e = RunRes Array e
328
+
329
+ type RunResM s e = RunRes (MArray s ) e
330
+
316
331
run :: (forall s . ST s (MArray s e )) -> Array e
317
332
run act = runST $ act >>= unsafeFreeze
318
333
{-# INLINE run #-}
319
334
335
+ runInternal :: (forall s . ST s (RunResM s e )) -> RunResA e
336
+ runInternal act = runST $ do
337
+ RunRes s mary <- act
338
+ ary <- unsafeFreeze mary
339
+ return (RunRes s ary)
340
+ {-# INLINE runInternal #-}
341
+
320
342
run2 :: (forall s . ST s (MArray s e , a )) -> (Array e , a )
321
343
run2 k = runST (do
322
344
(marr,b) <- k
@@ -388,7 +410,7 @@ updateM ary idx b =
388
410
where ! count = length ary
389
411
{-# INLINE updateM #-}
390
412
391
- -- | /O(n)/ Update the element at the given positio in this array, by
413
+ -- | /O(n)/ Update the element at the given position in this array, by
392
414
-- applying a function to it. Evaluates the element to WHNF before
393
415
-- inserting it into the array.
394
416
updateWith' :: Array e -> Int -> (e -> e ) -> Array e
@@ -397,6 +419,26 @@ updateWith' ary idx f
397
419
= update ary idx $! f x
398
420
{-# INLINE updateWith' #-}
399
421
422
+ -- | This newtype wrapper is to avoid confusion when local functions
423
+ -- take more than one paramenter of 'Int' type (see 'go' in
424
+ -- 'Data.HashMap.Base.unionWithKeyInternal').
425
+ newtype Size = Size { unSize :: Int }
426
+ deriving (Eq , Ord , Num , Integral , Enum , Real )
427
+
428
+ -- | Helper datatype used in 'updateWithInternal''. Used when a change in
429
+ -- a value's size must be returned along with the value itself (typically
430
+ -- a hashmap).
431
+ data Sized a = Sized {- # UNPACK #-} !Size ! a
432
+
433
+ -- | /O(n)/ Update the element at the given position in this array, by
434
+ -- applying a function to it. Evaluates the element to WHNF before
435
+ -- inserting it into the array.
436
+ updateWithInternal' :: Array e -> Int -> (e -> Sized e ) -> RunResA e
437
+ updateWithInternal' ary idx f =
438
+ let Sized sz e = f (index ary idx)
439
+ in RunRes sz (update ary idx e)
440
+ {-# INLINE updateWithInternal' #-}
441
+
400
442
-- | /O(1)/ Update the element at the given position in this array,
401
443
-- without copying.
402
444
unsafeUpdateM :: Array e -> Int -> e -> ST s ()
0 commit comments