Skip to content

Commit 707209c

Browse files
andrewthadtreeowl
authored andcommitted
Add strict map functions for Array and SmallArray (#138)
Add strict map functions for `Array` and `SmallArray`.
1 parent b43b2dd commit 707209c

File tree

3 files changed

+39
-6
lines changed

3 files changed

+39
-6
lines changed

Data/Primitive/Array.hs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module Data.Primitive.Array (
2323
cloneArray, cloneMutableArray,
2424
sizeofArray, sizeofMutableArray,
2525
fromListN, fromList,
26+
mapArray',
2627
unsafeTraverseArray
2728
) where
2829

@@ -559,6 +560,21 @@ unsafeTraverseArray f = \ !ary ->
559560
go 0 mary
560561
{-# INLINE unsafeTraverseArray #-}
561562

563+
-- | Strict map over the elements of the array.
564+
mapArray' :: (a -> b) -> Array a -> Array b
565+
mapArray' f a =
566+
createArray (sizeofArray a) (die "mapArray'" "impossible") $ \mb ->
567+
let go i | i == sizeofArray a
568+
= return ()
569+
| otherwise
570+
= do x <- indexArrayM a i
571+
-- We use indexArrayM here so that we will perform the
572+
-- indexing eagerly even if f is lazy.
573+
let !y = f x
574+
writeArray mb i y >> go (i+1)
575+
in go 0
576+
{-# INLINE mapArray' #-}
577+
562578
arrayFromListN :: Int -> [a] -> Array a
563579
arrayFromListN n l =
564580
createArray n (die "fromListN" "uninitialized element") $ \sma ->

Data/Primitive/SmallArray.hs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ module Data.Primitive.SmallArray
5757
, sizeofSmallMutableArray
5858
, smallArrayFromList
5959
, smallArrayFromListN
60+
, mapSmallArray'
6061
, unsafeTraverseSmallArray
6162
) where
6263

@@ -436,6 +437,20 @@ unsafeTraverseSmallArray f (SmallArray ar) = SmallArray `liftM` unsafeTraverseAr
436437
#endif
437438
{-# INLINE unsafeTraverseSmallArray #-}
438439

440+
-- | Strict map over the elements of the array.
441+
mapSmallArray' :: (a -> b) -> SmallArray a -> SmallArray b
442+
#if HAVE_SMALL_ARRAY
443+
mapSmallArray' f sa = createSmallArray (length sa) (die "mapSmallArray'" "impossible") $ \smb ->
444+
fix ? 0 $ \go i ->
445+
when (i < length sa) $ do
446+
x <- indexSmallArrayM sa i
447+
let !y = f x
448+
writeSmallArray smb i y *> go (i+1)
449+
#else
450+
mapSmallArray' f (SmallArray ar) = SmallArray (mapArray' f ar)
451+
#endif
452+
{-# INLINE mapSmallArray' #-}
453+
439454
#ifndef HAVE_SMALL_ARRAY
440455
runSmallArray
441456
:: (forall s. ST s (SmallMutableArray s a))

test/main.hs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,31 +45,33 @@ main = do
4545
, lawsToTest (QCC.ordLaws (Proxy :: Proxy (Array Int)))
4646
, lawsToTest (QCC.monoidLaws (Proxy :: Proxy (Array Int)))
4747
, lawsToTest (QCC.showReadLaws (Proxy :: Proxy (Array Int)))
48-
#if MIN_VERSION_base(4,7,0)
49-
, lawsToTest (QCC.isListLaws (Proxy :: Proxy (Array Int)))
50-
#endif
5148
#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)
5249
, lawsToTest (QCC.functorLaws (Proxy1 :: Proxy1 Array))
5350
, lawsToTest (QCC.applicativeLaws (Proxy1 :: Proxy1 Array))
5451
, lawsToTest (QCC.monadLaws (Proxy1 :: Proxy1 Array))
5552
, lawsToTest (QCC.foldableLaws (Proxy1 :: Proxy1 Array))
5653
, lawsToTest (QCC.traversableLaws (Proxy1 :: Proxy1 Array))
54+
#endif
55+
#if MIN_VERSION_base(4,7,0)
56+
, lawsToTest (QCC.isListLaws (Proxy :: Proxy (Array Int)))
57+
, TQC.testProperty "mapArray'" (QCCL.mapProp int16 int32 mapArray')
5758
#endif
5859
]
5960
, testGroup "SmallArray"
6061
[ lawsToTest (QCC.eqLaws (Proxy :: Proxy (SmallArray Int)))
6162
, lawsToTest (QCC.ordLaws (Proxy :: Proxy (SmallArray Int)))
6263
, lawsToTest (QCC.monoidLaws (Proxy :: Proxy (SmallArray Int)))
6364
, lawsToTest (QCC.showReadLaws (Proxy :: Proxy (Array Int)))
64-
#if MIN_VERSION_base(4,7,0)
65-
, lawsToTest (QCC.isListLaws (Proxy :: Proxy (SmallArray Int)))
66-
#endif
6765
#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)
6866
, lawsToTest (QCC.functorLaws (Proxy1 :: Proxy1 SmallArray))
6967
, lawsToTest (QCC.applicativeLaws (Proxy1 :: Proxy1 SmallArray))
7068
, lawsToTest (QCC.monadLaws (Proxy1 :: Proxy1 SmallArray))
7169
, lawsToTest (QCC.foldableLaws (Proxy1 :: Proxy1 SmallArray))
7270
, lawsToTest (QCC.traversableLaws (Proxy1 :: Proxy1 SmallArray))
71+
#endif
72+
#if MIN_VERSION_base(4,7,0)
73+
, lawsToTest (QCC.isListLaws (Proxy :: Proxy (SmallArray Int)))
74+
, TQC.testProperty "mapSmallArray'" (QCCL.mapProp int16 int32 mapSmallArray')
7375
#endif
7476
]
7577
, testGroup "ByteArray"

0 commit comments

Comments
 (0)