/
ST.purs
162 lines (138 loc) · 4.23 KB
/
ST.purs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
-- | Helper functions for working with mutable arrays using the `ST` effect.
-- |
-- | This module can be used when performance is important and mutation is a local effect.
module Data.Array.ST
( STArray(..)
, Assoc
, withArray
, empty
, peek
, poke
, push
, modify
, pushAll
, splice
, sort
, sortBy
, sortWith
, freeze
, thaw
, unsafeFreeze
, unsafeThaw
, toAssocArray
) where
import Prelude
import Control.Monad.ST (ST, kind Region)
import Data.Maybe (Maybe(..))
import Unsafe.Coerce (unsafeCoerce)
-- | A reference to a mutable array.
-- |
-- | The first type parameter represents the memory region which the array belongs to.
-- | The second type parameter defines the type of elements of the mutable array.
-- |
-- | The runtime representation of a value of type `STArray h a` is the same as that of `Array a`,
-- | except that mutation is allowed.
foreign import data STArray :: Region -> Type -> Type
-- | An element and its index.
type Assoc a = { value :: a, index :: Int }
-- | Perform an effect requiring a mutable array on a copy of an immutable array,
-- | safely returning the result as an immutable array.
withArray
:: forall h a b
. (STArray h a -> ST h b)
-> Array a
-> ST h (Array a)
withArray f xs = do
result <- thaw xs
_ <- f result
unsafeFreeze result
-- | O(1). Convert a mutable array to an immutable array, without copying. The mutable
-- | array must not be mutated afterwards.
unsafeFreeze :: forall h a. STArray h a -> ST h (Array a)
unsafeFreeze = pure <<< (unsafeCoerce :: STArray h a -> Array a)
-- | O(1) Convert an immutable array to a mutable array, without copying. The input
-- | array must not be used afterward.
unsafeThaw :: forall h a. Array a -> ST h (STArray h a)
unsafeThaw = pure <<< (unsafeCoerce :: Array a -> STArray h a)
-- | Create an empty mutable array.
foreign import empty :: forall h a. ST h (STArray h a)
-- | Create a mutable copy of an immutable array.
thaw :: forall h a. Array a -> ST h (STArray h a)
thaw = copyImpl
-- | Sort a mutable array in place.
sort :: forall a h. Ord a => STArray h a -> ST h (STArray h a)
sort = sortBy compare
-- | Sort a mutable array in place using a comparison function.
sortBy
:: forall a h
. (a -> a -> Ordering)
-> STArray h a
-> ST h (STArray h a)
sortBy comp = sortByImpl comp'
where
comp' x y = case comp x y of
GT -> 1
EQ -> 0
LT -> -1
foreign import sortByImpl
:: forall a h
. (a -> a -> Int)
-> STArray h a
-> ST h (STArray h a)
-- | Sort a mutable array in place based on a projection.
sortWith
:: forall a b h
. Ord b
=> (a -> b)
-> STArray h a
-> ST h (STArray h a)
sortWith f = sortBy (comparing f)
-- | Create an immutable copy of a mutable array.
freeze :: forall h a. STArray h a -> ST h (Array a)
freeze = copyImpl
foreign import copyImpl :: forall h a b. a -> ST h b
-- | Read the value at the specified index in a mutable array.
peek
:: forall h a
. Int
-> STArray h a
-> ST h (Maybe a)
peek = peekImpl Just Nothing
foreign import peekImpl
:: forall h a r
. (a -> r)
-> r
-> Int
-> STArray h a
-> (ST h r)
-- | Change the value at the specified index in a mutable array.
foreign import poke :: forall h a. Int -> a -> STArray h a -> ST h Boolean
-- | Append an element to the end of a mutable array. Returns the new length of
-- | the array.
push :: forall h a. a -> STArray h a -> ST h Int
push a = pushAll [a]
-- | Append the values in an immutable array to the end of a mutable array.
-- | Returns the new length of the mutable array.
foreign import pushAll
:: forall h a
. Array a
-> STArray h a
-> ST h Int
-- | Mutate the element at the specified index using the supplied function.
modify :: forall h a. Int -> (a -> a) -> STArray h a -> ST h Boolean
modify i f xs = do
entry <- peek i xs
case entry of
Just x -> poke i (f x) xs
Nothing -> pure false
-- | Remove and/or insert elements from/into a mutable array at the specified index.
foreign import splice
:: forall h a
. Int
-> Int
-> Array a
-> STArray h a
-> ST h (Array a)
-- | Create an immutable copy of a mutable array, where each element
-- | is labelled with its index in the original array.
foreign import toAssocArray :: forall h a. STArray h a -> ST h (Array (Assoc a))