on c3c52cd help sign in
elk/libraries/Array.elm
198 lines 5.6 kB history raw
1module Array where
3{-| A library for fast immutable arrays. The elements in an array must have the
4same type. The arrays are implemented in Relaxed Radix Balanced-Trees for fast
5reads, updates, and appends.
7# Creating Arrays
8@docs empty, repeat, initialize, fromList
10# Basics
11@docs length, push, append
13# Get and Set
14@docs get, getOrElse, getOrFail, set
16# Taking Arrays Apart
17@docs slice, toList, toIndexedList
19# Mapping and Folding
20@docs map, indexedMap, foldl, foldr
21-}
23import Native.Array
24import Basics (..)
25import Maybe (..)
26import List
28data Array a = Array
30{-| Initialize an array. `initialize n f` creates an array of length `n` with
31the element at index `i` initialized to the result of `(f i)`.
33 initialize 4 id == fromList [0,1,2,3]
34 initialize 4 (\n -> n*n) == fromList [0,1,4,9]
35 initialize 4 (always 0) == fromList [0,0,0,0]
36-}
37initialize : Int -> (Int -> a) -> Array a
38initialize = Native.Array.initialize
40{-| Creates an array with a given length, filled with a default element.
42 repeat 5 0 == fromList [0,0,0,0,0]
43 repeat 3 "cat" == fromList ["cat","cat","cat"]
45Notice that `repeat 3 x` is the same as `initialize 3 (always x)`.
46-}
47repeat : Int -> a -> Array a
48repeat n e = initialize n (always e)
50{-| Create an array from a list. -}
51fromList : [a] -> Array a
52fromList = Native.Array.fromList
54{-| Create a list of elements from an array.
56 toList (fromList [3,5,8]) == [3,5,8]
57-}
58toList : Array a -> [a]
59toList = Native.Array.toList
61-- TODO: make this a native function.
62{-| Create an indexed list from an array. Each element of the array will be
63paired with its index.
65 toIndexedList (fromList ["cat","dog"]) == [(0,"cat"), (1,"dog")]
66-}
67toIndexedList : Array a -> [(Int, a)]
68toIndexedList array =
69 List.zip [ 0 .. Native.Array.length array - 1 ] (Native.Array.toList array)
71{-| Apply a function on every element in an array.
73 map sqrt (fromList [1,4,9]) == fromList [1,2,3]
74-}
75map : (a -> b) -> Array a -> Array b
76map = Native.Array.map
78{-| Apply a function on every element with its index as first argument.
80 indexedMap (*) (fromList [5,5,5]) == fromList [0,5,10]
81-}
82indexedMap : (Int -> a -> b) -> Array a -> Array b
83indexedMap = Native.Array.indexedMap
85{-| Reduce an array from the left. Read `foldl` as “fold from the left”.
87 foldl (::) [] (fromList [1,2,3]) == [3,2,1]
88-}
89foldl : (a -> b -> b) -> b -> Array a -> b
90foldl = Native.Array.foldl
92{-| Reduce an array from the right. Read `foldr` as “fold from the right”.
94 foldr (+) 0 (repeat 3 5) == 15
95-}
96foldr : (a -> b -> b) -> b -> Array a -> b
97foldr = Native.Array.foldr
99{-| Keep only elements that satisfy the predicate:
101 filter isEven (fromList [1..6]) == (fromList [2,4,6])
102-}
103filter : (a -> Bool) -> Array a -> Array a
104filter isOkay arr =
105 let update x xs = if isOkay x then Native.Array.push x xs else xs
106 in
107 Native.Array.foldl update Native.Array.empty arr
109{-| Return an empty array.
111 length empty == 0
112-}
113empty : Array a
114empty = Native.Array.empty
116{-| Push an element to the end of an array.
118 push 3 (fromList [1,2]) == fromList [1,2,3]
119-}
120push : a -> Array a -> Array a
121push = Native.Array.push
123{-| Get the element at a particular index.
125 getOrFail 0 (A.fromList [0,1,2]) == 0
127Warning: this function will result in a runtime error if the index is not found,
128so it is best to use `get` or `getOrElse` unless you are sure the index will be
129found.
130-}
131getOrFail : Int -> Array a -> a
132getOrFail = Native.Array.get
134{-| Return Just the element at the index or Nothing if the index is out of range.
136 get 0 (fromList [0,1,2]) == Just 0
137 get 2 (fromList [0,1,2]) == Just 2
138 get 5 (fromList [0,1,2]) == Nothing
139 get -1 (fromList [0,1,2]) == Nothing
140-}
141get : Int -> Array a -> Maybe a
142get i array =
143 if 0 <= i && i < Native.Array.length array
144 then Just (Native.Array.get i array)
145 else Nothing
147{-| Get the element at the index. Or if the index is out of range, a default
148value is returned.
150 getOrElse 0 2 (fromList [0,1,2]) == 2
151 getOrElse 0 5 (fromList [0,1,2]) == 0
152-}
153getOrElse : a -> Int -> Array a -> a
154getOrElse default i array =
155 if 0 <= i && i < Native.Array.length array
156 then Native.Array.get i array
157 else default
159{-| Set the element at a particular index. Returns an updated array.
160If the index is out of range, the array is unaltered.
162 set 1 7 (fromList [1,2,3]) == fromList [1,7,3]
163-}
164set : Int -> a -> Array a -> Array a
165set = Native.Array.set
167{-| Get a sub-section of an array: `(slice start end array)`. The `start` is a
168zero-based index where we will start our slice. The `end` is a zero-based index
169that indicates the end of the slice. The slice extracts up to but not including
170`end`.
172 slice 0 3 (fromList [0,1,2,3,4]) == fromList [0,1,2]
173 slice 1 4 (fromList [0,1,2,3,4]) == fromList [1,2,3]
175Both the `start` and `end` indexes can be negative, indicating an offset from
176the end of the array.
178 slice 1 -1 (fromList [0,1,2,3,4]) == fromList [1,2,3]
179 slice -2 5 (fromList [0,1,2,3,4]) == fromList [3,4]
181This makes it pretty easy to `pop` the last element off of an array: `slice 0 -1 array`
182-}
183slice : Int -> Int -> Array a -> Array a
184slice = Native.Array.slice
186{-| Return the length of an array.
188 length (fromList [1,2,3]) == 3
189-}
190length : Array a -> Int
191length = Native.Array.length
193{-| Append two arrays to a new one.
195 append (repeat 2 42) (repeat 3 81) == fromList [42,42,81,81,81]
196-}
197append : Array a -> Array a -> Array a
198append = Native.Array.append