Skip to content

Commit 162f43a

Browse files
committed
Restrict to a closed row in runSTArray
1 parent 766b7f4 commit 162f43a

File tree

3 files changed

+61
-46
lines changed

3 files changed

+61
-46
lines changed

src/Data/Array.purs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ import Prelude
115115
import Control.Alt ((<|>))
116116
import Control.Alternative (class Alternative)
117117
import Control.Lazy (class Lazy, defer)
118-
import Control.Monad.Eff (Eff, runPure)
118+
import Control.Monad.Eff (Eff)
119119
import Control.Monad.Rec.Class (class MonadRec, Step(..), tailRecM2)
120120
import Control.Monad.ST (ST)
121121

@@ -554,21 +554,20 @@ group' = group <<< sort
554554
-- | specified equivalence relation to detemine equality.
555555
groupBy :: forall a. (a -> a -> Boolean) -> Array a -> Array (NonEmpty Array a)
556556
groupBy op xs =
557-
runPure do
558-
runGroupedSTArray do
559-
result <- emptySTArray
560-
iter <- iterator (xs !! _)
561-
iterate iter \x -> do
562-
sub <- emptySTArray
563-
pushSTArray result (x :| sub)
564-
pushWhile (op x) iter sub
565-
pure result
557+
runGroupedSTArray do
558+
result <- emptySTArray
559+
iter <- iterator (xs !! _)
560+
iterate iter \x -> do
561+
sub <- emptySTArray
562+
pushSTArray result (x :| sub)
563+
pushWhile (op x) iter sub
564+
pure result
566565
where
567566
runGroupedSTArray
568-
:: forall b r
569-
. (forall h. Eff (st :: ST h | r) (STArray h (NonEmpty (STArray h) b)))
570-
-> Eff r (Array (NonEmpty Array b))
571-
runGroupedSTArray a = map unwrap (runSTArray' (map Grouped a))
567+
:: forall b
568+
. (forall h. Eff (st :: ST h) (STArray h (NonEmpty (STArray h) b)))
569+
-> Array (NonEmpty Array b)
570+
runGroupedSTArray a = unwrap (runSTArray' (map Grouped a))
572571

573572
newtype Grouped a arr = Grouped (arr (NonEmpty arr a))
574573
derive instance newtypeGrouped :: Newtype (Grouped a arr) _

src/Data/Array/ST.purs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ module Data.Array.ST
1818
) where
1919

2020
import Prelude
21-
import Control.Monad.Eff (Eff)
21+
import Control.Monad.Eff (Eff, Pure, runPure)
2222
import Control.Monad.ST (ST)
2323
import Data.Maybe (Maybe(..))
2424
import Data.Newtype (class Newtype, unwrap)
@@ -43,25 +43,41 @@ derive instance newtypeId :: Newtype (Id a f) _
4343
-- | Freeze a mutable array, creating an immutable array. Use this function as you would use
4444
-- | `runST` to freeze a mutable reference.
4545
-- |
46-
-- | The rank-2 type prevents the reference from escaping the scope of `runSTArray`.
46+
-- | The rank-2 type prevents the reference from escaping the scope of `runSTArray'`,
47+
-- | and the closed row on the `Eff` computation prevents the reference from
48+
-- | escaping into other parts of your program via native effects such as `setTimeout`.
49+
-- |
50+
-- | You can also return an immutable copy of an `STArray` from an `ST` computation
51+
-- | by using `freeze` combined with `runST`. However, when possible, you should
52+
-- | prefer this function, because it is `O(1)`. By contrast, `freeze` must copy the
53+
-- | underlying array and is therefore `O(n)`.
4754
runSTArray
48-
:: forall a r
49-
. (forall h. Eff (st :: ST h | r) (STArray h a))
50-
-> Eff r (Array a)
51-
runSTArray a = map unwrap (runSTArray' (map Id a))
55+
:: forall a
56+
. (forall h. Eff (st :: ST h) (STArray h a))
57+
-> Array a
58+
runSTArray a = unwrap (runSTArray' (map Id a))
5259

5360
-- | Freeze all mutable arrays in some structure, creating a version of the
5461
-- | same structure where all mutable arrays are replaced with immutable
5562
-- | arrays. Use this function as you would use `runST` to freeze a mutable
5663
-- | reference.
5764
-- |
58-
-- | The rank-2 type prevents the reference from escaping the scope of `runSTArray'`.
65+
-- | The rank-2 type prevents the reference from escaping the scope of `runSTArray'`,
66+
-- | and the closed row on the `Eff` computation prevents the reference from
67+
-- | escaping into other parts of your program via native effects such as `setTimeout`.
68+
-- |
69+
-- | You can also return an immutable copy of an `STArray` from an `ST` computation
70+
-- | by using `freeze` combined with `runST`. However, when possible, you should
71+
-- | prefer this function, because it is `O(1)`. By contrast, `freeze` must copy the
72+
-- | underlying array and is therefore `O(n)`.
5973
runSTArray'
60-
:: forall f r
61-
. (forall h. Eff (st :: ST h | r) (f (STArray h)))
62-
-> Eff r (f Array)
63-
runSTArray' =
64-
unsafeCoerce
74+
:: forall f
75+
. (forall h. Eff (st :: ST h) (f (STArray h)))
76+
-> f Array
77+
runSTArray' x = runPure (go x)
78+
where
79+
go :: (forall h. Eff (st :: ST h) (f (STArray h))) -> Pure (f Array)
80+
go = unsafeCoerce
6581

6682
-- | Create an empty mutable array.
6783
foreign import emptySTArray :: forall a h r. Eff (st :: ST h | r) (STArray h a)

test/Test/Data/Array/ST.purs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ testArrayST = do
1717

1818
log "emptySTArray should produce an empty array"
1919

20-
assert $ runPure (runSTArray emptySTArray) == nil
20+
assert $ runSTArray emptySTArray == nil
2121

2222
log "thaw should produce an STArray from a standard array"
2323

24-
assert $ runPure (runSTArray (thaw [1, 2, 3])) == [1, 2, 3]
24+
assert $ runSTArray (thaw [1, 2, 3]) == [1, 2, 3]
2525

2626
log "freeze should produce a standard array from an STArray"
2727

@@ -31,28 +31,28 @@ testArrayST = do
3131

3232
log "pushSTArray should append a value to the end of the array"
3333

34-
assert $ runPure (runSTArray (do
34+
assert $ runSTArray (do
3535
arr <- emptySTArray
3636
pushSTArray arr 1
3737
pushSTArray arr 2
38-
pure arr)) == [1, 2]
38+
pure arr) == [1, 2]
3939

40-
assert $ runPure (runSTArray (do
40+
assert $ runSTArray (do
4141
arr <- thaw [1, 2, 3]
4242
pushSTArray arr 4
43-
pure arr)) == [1, 2, 3, 4]
43+
pure arr) == [1, 2, 3, 4]
4444

4545
log "pushAllSTArray should append multiple values to the end of the array"
4646

47-
assert $ runPure (runSTArray (do
47+
assert $ runSTArray (do
4848
arr <- emptySTArray
4949
pushAllSTArray arr [1, 2]
50-
pure arr)) == [1, 2]
50+
pure arr) == [1, 2]
5151

52-
assert $ runPure (runSTArray (do
52+
assert $ runSTArray (do
5353
arr <- thaw [1, 2, 3]
5454
pushAllSTArray arr [4, 5, 6]
55-
pure arr)) == [1, 2, 3, 4, 5, 6]
55+
pure arr) == [1, 2, 3, 4, 5, 6]
5656

5757
log "peekSTArray should return Nothing when peeking a value outside the array bounds"
5858

@@ -104,24 +104,24 @@ testArrayST = do
104104

105105
log "pokeSTArray should replace the value at the specified index"
106106

107-
assert $ runPure (runSTArray (do
107+
assert $ runSTArray (do
108108
arr <- thaw [1]
109109
pokeSTArray arr 0 10
110-
pure arr)) == [10]
110+
pure arr) == [10]
111111

112112
log "pokeSTArray should do nothing when attempting to modify a value outside the array bounds"
113113

114-
assert $ runPure (runSTArray (do
114+
assert $ runSTArray (do
115115
arr <- thaw [1]
116116
pokeSTArray arr 1 2
117-
pure arr)) == [1]
117+
pure arr) == [1]
118118

119119
log "spliceSTArray should be able to delete multiple items at a specified index"
120120

121-
assert $ runPure (runSTArray (do
121+
assert $ runSTArray (do
122122
arr <- thaw [1, 2, 3, 4, 5]
123123
spliceSTArray arr 1 3 []
124-
pure arr)) == [1, 5]
124+
pure arr) == [1, 5]
125125

126126
log "spliceSTArray should return the items removed"
127127

@@ -131,17 +131,17 @@ testArrayST = do
131131

132132
log "spliceSTArray should be able to insert multiple items at a specified index"
133133

134-
assert $ runPure (runSTArray (do
134+
assert $ runSTArray (do
135135
arr <- thaw [1, 2, 3, 4, 5]
136136
spliceSTArray arr 1 0 [0, 100]
137-
pure arr)) == [1, 0, 100, 2, 3, 4, 5]
137+
pure arr) == [1, 0, 100, 2, 3, 4, 5]
138138

139139
log "spliceSTArray should be able to delete and insert at the same time"
140140

141-
assert $ runPure (runSTArray (do
141+
assert $ runSTArray (do
142142
arr <- thaw [1, 2, 3, 4, 5]
143143
spliceSTArray arr 1 2 [0, 100]
144-
pure arr)) == [1, 0, 100, 4, 5]
144+
pure arr) == [1, 0, 100, 4, 5]
145145

146146
log "toAssocArray should return all items in the array with the correct indices and values"
147147

0 commit comments

Comments
 (0)