Skip to content

Commit b6c5f5b

Browse files
matthewleonpaf31
authored andcommitted
batch update and modify functions (#101)
* update and modify at indices Also exports ST utility functions `modifySTArray` and `withArray`. * change export ordering
1 parent b863b82 commit b6c5f5b

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

src/Data/Array.purs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ module Data.Array
5959
, insertAt
6060
, deleteAt
6161
, updateAt
62+
, updateAtIndices
6263
, modifyAt
64+
, modifyAtIndices
6365
, alterAt
6466

6567
, reverse
@@ -115,15 +117,15 @@ import Control.Alternative (class Alternative)
115117
import Control.Lazy (class Lazy, defer)
116118
import Control.Monad.Rec.Class (class MonadRec, Step(..), tailRecM2)
117119
import Control.Monad.ST (pureST)
118-
import Data.Array.ST (unsafeFreeze, emptySTArray, pushSTArray)
120+
import Data.Array.ST (unsafeFreeze, emptySTArray, pokeSTArray, pushSTArray, modifySTArray, withArray)
119121
import Data.Array.ST.Iterator (iterator, iterate, pushWhile)
120-
import Data.Foldable (class Foldable, foldl, foldr)
122+
import Data.Foldable (class Foldable, foldl, foldr, traverse_)
121123
import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports
122124
import Data.Maybe (Maybe(..), maybe, isJust, fromJust)
123125
import Data.NonEmpty (NonEmpty, (:|))
124126
import Data.Traversable (scanl, scanr) as Exports
125127
import Data.Traversable (sequence, traverse)
126-
import Data.Tuple (Tuple(..))
128+
import Data.Tuple (Tuple(..), uncurry)
127129
import Data.Unfoldable (class Unfoldable, unfoldr)
128130
import Partial.Unsafe (unsafePartial)
129131

@@ -445,6 +447,17 @@ mapWithIndex :: forall a b. (Int -> a -> b) -> Array a -> Array b
445447
mapWithIndex f xs =
446448
zipWith f (range 0 (length xs - 1)) xs
447449

450+
-- | Change the elements at the specified indices in index/value pairs.
451+
-- | Out-of-bounds indices will have no effect.
452+
updateAtIndices :: forall t a. Foldable t => t (Tuple Int a) -> Array a -> Array a
453+
updateAtIndices us xs =
454+
pureST (withArray (\res -> traverse_ (uncurry $ pokeSTArray res) us) xs)
455+
456+
-- | Apply a function to the element at the specified indices,
457+
-- | creating a new array. Out-of-bounds indices will have no effect.
458+
modifyAtIndices :: forall t a. Foldable t => t Int -> (a -> a) -> Array a -> Array a
459+
modifyAtIndices is f xs =
460+
pureST (withArray (\res -> traverse_ (\i -> modifySTArray res i f) is) xs)
448461

449462
--------------------------------------------------------------------------------
450463
-- Sorting ---------------------------------------------------------------------

src/Data/Array/ST.purs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ module Data.Array.ST
66
( STArray(..)
77
, Assoc()
88
, runSTArray
9+
, withArray
910
, emptySTArray
1011
, peekSTArray
1112
, pokeSTArray
1213
, pushSTArray
14+
, modifySTArray
1315
, pushAllSTArray
1416
, spliceSTArray
1517
, freeze, thaw
@@ -47,6 +49,18 @@ foreign import runSTArray
4749
. (forall h. Eff (st :: ST h | r) (STArray h a))
4850
-> Eff r (Array a)
4951

52+
-- Perform an effect requiring a mutable array on a copy of an immutable array,
53+
-- safely returning the result as an immutable array.
54+
withArray
55+
:: forall a b r h
56+
. (STArray h a -> Eff (st :: ST h | r) b)
57+
-> Array a
58+
-> Eff (st :: ST h | r) (Array a)
59+
withArray f xs = do
60+
result <- thaw xs
61+
_ <- f result
62+
unsafeFreeze result
63+
5064
-- | O(1). Convert a mutable array to an immutable array, without copying. The mutable
5165
-- | array must not be mutated afterwards.
5266
unsafeFreeze :: forall a r h. STArray h a -> Eff (st :: ST h | r) (Array a)
@@ -97,6 +111,14 @@ foreign import pushAllSTArray
97111
-> Array a
98112
-> Eff (st :: ST h | r) Int
99113

114+
-- | Mutate the element at the specified index using the supplied function.
115+
modifySTArray :: forall a h r. STArray h a -> Int -> (a -> a) -> Eff (st :: ST h | r) Boolean
116+
modifySTArray xs i f = do
117+
entry <- peekSTArray xs i
118+
case entry of
119+
Just x -> pokeSTArray xs i (f x)
120+
Nothing -> pure false
121+
100122
-- | Remove and/or insert elements from/into a mutable array at the specified index.
101123
foreign import spliceSTArray
102124
:: forall a h r

test/Test/Data/Array.purs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,16 @@ testArray = do
222222
log "mapWithIndex applies a function with an index for every element"
223223
assert $ A.mapWithIndex (\i x -> x - i) [9,8,7,6,5] == [9,7,5,3,1]
224224

225+
log "updateAtIndices changes the elements at specified indices"
226+
assert $ A.updateAtIndices
227+
[Tuple 0 false, Tuple 2 false, Tuple 8 false]
228+
[true, true, true, true] ==
229+
[false, true, false, true]
230+
231+
log "modifyAtIndices modifies the elements at specified indices"
232+
assert $ A.modifyAtIndices [0, 2, 8] not [true, true, true, true] ==
233+
[false, true, false, true]
234+
225235
log "sort should reorder a list into ascending order based on the result of compare"
226236
assert $ A.sort [1, 3, 2, 5, 6, 4] == [1, 2, 3, 4, 5, 6]
227237

0 commit comments

Comments
 (0)