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
@@ -317,10 +325,24 @@ unsafeThaw ary
317
325
(# s', mary # ) -> (# s', marray mary (length ary) # )
318
326
{-# INLINE unsafeThaw #-}
319
327
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
+
320
335
run :: (forall s . ST s (MArray s e )) -> Array e
321
336
run act = runST $ act >>= unsafeFreeze
322
337
{-# INLINE run #-}
323
338
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
+
324
346
run2 :: (forall s . ST s (MArray s e , a )) -> (Array e , a )
325
347
run2 k = runST (do
326
348
(marr,b) <- k
@@ -392,7 +414,7 @@ updateM ary idx b =
392
414
where ! count = length ary
393
415
{-# INLINE updateM #-}
394
416
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
396
418
-- applying a function to it. Evaluates the element to WHNF before
397
419
-- inserting it into the array.
398
420
updateWith' :: Array e -> Int -> (e -> e ) -> Array e
@@ -401,6 +423,26 @@ updateWith' ary idx f
401
423
= update ary idx $! f x
402
424
{-# INLINE updateWith' #-}
403
425
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
+
404
446
-- | /O(1)/ Update the element at the given position in this array,
405
447
-- without copying.
406
448
unsafeUpdateM :: Array e -> Int -> e -> ST s ()
0 commit comments