@@ -5,16 +5,22 @@ import Prelude
55import Control.Monad.Eff (Eff )
66import Control.Monad.Eff.Console (CONSOLE , log )
77import Data.Array.NonEmpty as NEA
8- import Data.Foldable (sum )
8+ import Data.Const (Const (..))
9+ import Data.Foldable (for_ , sum , traverse_ )
10+ import Data.FunctorWithIndex (mapWithIndex )
911import Data.Maybe (Maybe (..), fromJust )
1012import Data.Monoid.Additive (Additive (..))
1113import Data.Semigroup.Foldable (foldMap1 )
1214import Data.Semigroup.Traversable (traverse1 )
15+ import Data.Tuple (Tuple (..))
1316import Partial.Unsafe (unsafePartial )
1417import Test.Assert (ASSERT , assert )
1518
1619testNonEmptyArray :: forall eff . Eff (console :: CONSOLE , assert :: ASSERT | eff ) Unit
1720testNonEmptyArray = do
21+ let fromArray :: forall a . Array a -> NEA.NonEmptyArray a
22+ fromArray = unsafePartial fromJust <<< NEA .fromArray
23+
1824 log " singleton should construct an array with a single value"
1925 assert $ NEA .toArray (NEA .singleton 1 ) == [1 ]
2026 assert $ NEA .toArray (NEA .singleton " foo" ) == [" foo" ]
@@ -33,15 +39,265 @@ testNonEmptyArray = do
3339
3440 log " length should return the number of items in an array"
3541 assert $ NEA .length (NEA .singleton 1 ) == 1
36- assert $ NEA .length (unsafePartial fromJust (NEA .fromArray [1 , 2 , 3 , 4 , 5 ]))
37- == 5
42+ assert $ NEA .length (fromArray [1 , 2 , 3 , 4 , 5 ]) == 5
43+
44+ log " cons should add an item to the start of an array"
45+ assert $ NEA .cons 4 (fromArray [1 , 2 , 3 ]) == fromArray [4 , 1 , 2 , 3 ]
46+ assert $ NEA .cons' 4 [1 , 2 , 3 ] == fromArray [4 , 1 , 2 , 3 ]
47+
48+ log " snoc should add an item to the end of an array"
49+ assert $ fromArray [1 , 2 , 3 ] `NEA.snoc` 4 == fromArray [1 , 2 , 3 , 4 ]
50+ assert $ [1 , 2 , 3 ] `NEA.snoc'` 4 == fromArray [1 , 2 , 3 , 4 ]
51+
52+ log " insert should add an item at the appropriate place in a sorted array"
53+ assert $ NEA .insert 1.5 (fromArray [1.0 , 2.0 , 3.0 ])
54+ == fromArray [1.0 , 1.5 , 2.0 , 3.0 ]
55+ assert $ NEA .insert 4 (fromArray [1 , 2 , 3 ]) == fromArray [1 , 2 , 3 , 4 ]
56+
57+ log " insertBy should add an item at the appropriate place in a sorted array using the specified comparison"
58+ assert $ NEA .insertBy (flip compare) 1.5 (fromArray [1.0 , 2.0 , 3.0 ])
59+ == fromArray [1.0 , 2.0 , 3.0 , 1.5 ]
60+
61+ log " head should return the first value of a non-empty array"
62+ assert $ NEA .head (fromArray [" foo" , " bar" ]) == " foo"
63+
64+ log " last should return the last value of a non-empty array"
65+ assert $ NEA .last (fromArray [" foo" , " bar" ]) == " bar"
66+
67+ log " tail should return an array containing all the items in an array apart from the first for a non-empty array"
68+ assert $ NEA .tail (fromArray [" foo" , " bar" , " baz" ]) == [" bar" , " baz" ]
69+
70+ log " init should return an array containing all the items in an array apart from the first for a non-empty array"
71+ assert $ NEA .init (fromArray [" foo" , " bar" , " baz" ]) == [" foo" , " bar" ]
72+
73+ log " uncons should split an array into a head and tail record"
74+ let u1 = NEA .uncons $ NEA .singleton 1
75+ assert $ u1.head == 1
76+ assert $ u1.tail == []
77+ let u2 = NEA .uncons $ fromArray [1 , 2 , 3 ]
78+ assert $ u2.head == 1
79+ assert $ u2.tail == [2 , 3 ]
80+
81+ log " unsnoc should split an array into an init and last record"
82+ let u3 = NEA .unsnoc $ NEA .singleton 1
83+ assert $ u3.init == []
84+ assert $ u3.last == 1
85+ let u4 = NEA .unsnoc $ fromArray [1 , 2 , 3 ]
86+ assert $ u4.init == [1 , 2 ]
87+ assert $ u4.last == 3
88+
89+ log " index should return Just x when the index is within the bounds of the array"
90+ assert $ NEA .index (fromArray [1 , 2 , 3 ]) 0 == Just 1
91+ assert $ NEA .index (fromArray [1 , 2 , 3 ]) 1 == Just 2
92+ assert $ NEA .index (fromArray [1 , 2 , 3 ]) 2 == Just 3
93+
94+ log " index should return Nothing when the index is outside of the bounds of the array"
95+ assert $ NEA .index (fromArray [1 , 2 , 3 ]) 6 == Nothing
96+ assert $ NEA .index (fromArray [1 , 2 , 3 ]) (-1 ) == Nothing
97+
98+ log " elemIndex should return the index of an item that a predicate returns true for in an array"
99+ assert $ NEA .elemIndex 1 (fromArray [1 , 2 , 1 ]) == Just 0
100+ assert $ NEA .elemIndex 4 (fromArray [1 , 2 , 1 ]) == Nothing
101+
102+ log " elemLastIndex should return the last index of an item in an array"
103+ assert $ NEA .elemLastIndex 1 (fromArray [1 , 2 , 1 ]) == Just 2
104+ assert $ NEA .elemLastIndex 4 (fromArray [1 , 2 , 1 ]) == Nothing
105+
106+ log " findIndex should return the index of an item that a predicate returns true for in an array"
107+ assert $ (NEA .findIndex (_ /= 1 ) (fromArray [1 , 2 , 1 ])) == Just 1
108+ assert $ (NEA .findIndex (_ == 3 ) (fromArray [1 , 2 , 1 ])) == Nothing
109+
110+ log " findLastIndex should return the last index of an item in an array"
111+ assert $ (NEA .findLastIndex (_ /= 1 ) (fromArray [2 , 1 , 2 ])) == Just 2
112+ assert $ (NEA .findLastIndex (_ == 3 ) (fromArray [2 , 1 , 2 ])) == Nothing
113+
114+ log " insertAt should add an item at the specified index"
115+ assert $ NEA .insertAt 0 1 (fromArray [2 , 3 ]) == Just (fromArray [1 , 2 , 3 ])
116+ assert $ NEA .insertAt 1 1 (fromArray [2 , 3 ]) == Just (fromArray [2 , 1 , 3 ])
117+ assert $ NEA .insertAt 2 1 (fromArray [2 , 3 ]) == Just (fromArray [2 , 3 , 1 ])
118+
119+ log " insertAt should return Nothing if the index is out of A.range"
120+ assert $ (NEA .insertAt 2 1 (NEA .singleton 1 )) == Nothing
121+
122+ log " deleteAt should remove an item at the specified index"
123+ assert $ (NEA .deleteAt 0 (fromArray [1 , 2 , 3 ])) == Just [2 , 3 ]
124+ assert $ (NEA .deleteAt 1 (fromArray [1 , 2 , 3 ])) == Just [1 , 3 ]
125+
126+ log " deleteAt should return Nothing if the index is out of A.range"
127+ assert $ (NEA .deleteAt 1 (NEA .singleton 1 )) == Nothing
128+
129+ log " updateAt should replace an item at the specified index"
130+ assert $ NEA .updateAt 0 9 (fromArray [1 , 2 , 3 ]) == Just (fromArray [9 , 2 , 3 ])
131+ assert $ NEA .updateAt 1 9 (fromArray [1 , 2 , 3 ]) == Just (fromArray [1 , 9 , 3 ])
132+
133+ log " updateAt should return Nothing if the index is out of A.range"
134+ assert $ NEA .updateAt 1 9 (NEA .singleton 0 ) == Nothing
135+
136+ log " modifyAt should update an item at the specified index"
137+ assert $ NEA .modifyAt 0 (_ + 1 ) (fromArray [1 , 2 , 3 ]) == Just (fromArray [2 , 2 , 3 ])
138+ assert $ NEA .modifyAt 1 (_ + 1 ) (fromArray [1 , 2 , 3 ]) == Just (fromArray [1 , 3 , 3 ])
139+
140+ log " modifyAt should return Nothing if the index is out of A.range"
141+ assert $ NEA .modifyAt 1 (_ + 1 ) (NEA .singleton 0 ) == Nothing
142+
143+ log " alterAt should update an item at the specified index when the function returns Just"
144+ assert $ NEA .alterAt 0 (Just <<< (_ + 1 )) (fromArray [1 , 2 , 3 ]) == Just [2 , 2 , 3 ]
145+ assert $ NEA .alterAt 1 (Just <<< (_ + 1 )) (fromArray [1 , 2 , 3 ]) == Just [1 , 3 , 3 ]
146+
147+ log " alterAt should drop an item at the specified index when the function returns Nothing"
148+ assert $ NEA .alterAt 0 (const Nothing ) (fromArray [1 , 2 , 3 ]) == Just [2 , 3 ]
149+ assert $ NEA .alterAt 1 (const Nothing ) (fromArray [1 , 2 , 3 ]) == Just [1 , 3 ]
150+
151+ log " alterAt should return Nothing if the index is out of NEA.range"
152+ assert $ NEA .alterAt 1 (Just <<< (_ + 1 )) (NEA .singleton 1 ) == Nothing
153+
154+ log " reverse should reverse the order of items in an array"
155+ assert $ NEA .reverse (fromArray [1 , 2 , 3 ]) == fromArray [3 , 2 , 1 ]
156+ assert $ NEA .reverse (NEA .singleton 0 ) == NEA .singleton 0
157+
158+ log " concat should join an array of arrays"
159+ assert $ NEA .concat (fromArray [fromArray [1 , 2 ], fromArray [3 , 4 ]] ) == fromArray [1 , 2 , 3 , 4 ]
160+
161+ log " concatMap should be equivalent to (concat <<< map)"
162+ assert $ NEA .concatMap doubleAndOrig (fromArray [1 , 2 , 3 ]) == NEA .concat (map doubleAndOrig (fromArray [1 , 2 , 3 ]))
163+
164+ log " filter should remove items that don't match a predicate"
165+ assert $ (NEA .filter odd <$> NEA .range 0 10 ) == Just [1 , 3 , 5 , 7 , 9 ]
166+
167+ log " filterA should remove items that don't match a predicate while using an applicative behaviour"
168+ assert $ NEA .filterA (Just <<< odd) (unsafePartial $ fromJust $ NEA .range 0 10 ) == Just [1 , 3 , 5 , 7 , 9 ]
169+ assert $ NEA .filterA (const Nothing ) (unsafePartial $ fromJust $ NEA .range 0 10 ) == Nothing
170+
171+ log " filterA should apply effects in the right order"
172+ assert $ NEA .filterA (Const <<< show) (unsafePartial $ fromJust $ NEA .range 1 5 ) == Const " 12345"
173+
174+ log " mapMaybe should transform every item in an array, throwing out Nothing values"
175+ assert $ NEA .mapMaybe (\x -> if x /= 0 then Just x else Nothing ) (fromArray [0 , 1 , 0 , 0 , 2 , 3 ]) == [1 , 2 , 3 ]
176+
177+ log " catMaybe should take an array of Maybe values and throw out Nothings"
178+ assert $ NEA .catMaybes (fromArray [Nothing , Just 2 , Nothing , Just 4 ]) == [2 , 4 ]
179+
180+ log " mapWithIndex applies a function with an index for every element"
181+ assert $ mapWithIndex (\i x -> x - i) (fromArray [9 ,8 ,7 ,6 ,5 ]) == fromArray [9 ,7 ,5 ,3 ,1 ]
182+
183+ log " updateAtIndices changes the elements at specified indices"
184+ assert $ NEA .updateAtIndices
185+ [Tuple 0 false , Tuple 2 false , Tuple 8 false ]
186+ (fromArray [true , true , true , true ]) ==
187+ fromArray [false , true , false , true ]
188+
189+ log " modifyAtIndices modifies the elements at specified indices"
190+ assert $ NEA .modifyAtIndices [0 , 2 , 8 ] not (fromArray [true , true , true , true ]) ==
191+ (fromArray [false , true , false , true ])
192+
193+ log " sort should reorder a list into ascending order based on the result of compare"
194+ assert $ NEA .sort (fromArray [1 , 3 , 2 , 5 , 6 , 4 ]) == fromArray [1 , 2 , 3 , 4 , 5 , 6 ]
195+
196+ log " sortBy should reorder a list into ascending order based on the result of a comparison function"
197+ assert $ NEA .sortBy (flip compare) (fromArray [1 , 3 , 2 , 5 , 6 , 4 ]) == fromArray [6 , 5 , 4 , 3 , 2 , 1 ]
198+
199+ log " sortWith should reorder a list into ascending order based on the result of compare over a projection"
200+ assert $ NEA .sortWith id (fromArray [1 , 3 , 2 , 5 , 6 , 4 ]) == fromArray [1 , 2 , 3 , 4 , 5 , 6 ]
201+
202+ log " take should keep the specified number of items from the front of an array, discarding the rest"
203+ assert $ NEA .take 1 (fromArray [1 , 2 , 3 ]) == [1 ]
204+ assert $ NEA .take 2 (fromArray [1 , 2 , 3 ]) == [1 , 2 ]
205+
206+ log " takeWhile should keep all values that match a predicate from the front of an array"
207+ assert $ NEA .takeWhile (_ /= 2 ) (fromArray [1 , 2 , 3 ]) == [1 ]
208+ assert $ NEA .takeWhile (_ /= 3 ) (fromArray [1 , 2 , 3 ]) == [1 , 2 ]
209+
210+ log " take should keep the specified number of items from the end of an array, discarding the rest"
211+ assert $ NEA .takeEnd 1 (fromArray [1 , 2 , 3 ]) == [3 ]
212+ assert $ NEA .takeEnd 2 (fromArray [1 , 2 , 3 ]) == [2 , 3 ]
213+
214+ log " drop should remove the specified number of items from the front of an array"
215+ assert $ NEA .drop 1 (fromArray [1 , 2 , 3 ]) == [2 , 3 ]
216+ assert $ NEA .drop 2 (fromArray [1 , 2 , 3 ]) == [3 ]
217+
218+ log " dropWhile should remove all values that match a predicate from the front of an array"
219+ assert $ NEA .dropWhile (_ /= 1 ) (fromArray [1 , 2 , 3 ]) == [1 , 2 , 3 ]
220+ assert $ NEA .dropWhile (_ /= 2 ) (fromArray [1 , 2 , 3 ]) == [2 , 3 ]
221+
222+ log " drop should remove the specified number of items from the end of an array"
223+ assert $ NEA .dropEnd 1 (fromArray [1 , 2 , 3 ]) == [1 , 2 ]
224+ assert $ NEA .dropEnd 2 (fromArray [1 , 2 , 3 ]) == [1 ]
225+
226+ log " span should split an array in two based on a predicate"
227+ let testSpan { p, input, init_, rest_ } = do
228+ let result = NEA .span p input
229+ assert $ result.init == init_
230+ assert $ result.rest == rest_
231+
232+ let oneToSeven = fromArray [1 , 2 , 3 , 4 , 5 , 6 , 7 ]
233+ testSpan { p: (_ < 4 ), input: oneToSeven, init_: [1 , 2 , 3 ], rest_: [4 , 5 , 6 , 7 ] }
234+
235+ log " nub should remove duplicate elements from the list, keeping the first occurence"
236+ assert $ NEA .nub (fromArray [1 , 2 , 2 , 3 , 4 , 1 ]) == fromArray [1 , 2 , 3 , 4 ]
237+
238+ log " nubBy should remove duplicate items from the list using a supplied predicate"
239+ let nubPred = \x y -> if odd x then false else x == y
240+ assert $ NEA .nubBy nubPred (fromArray [1 , 2 , 2 , 3 , 3 , 4 , 4 , 1 ]) == fromArray [1 , 2 , 3 , 3 , 4 , 1 ]
241+
242+ log " union should produce the union of two arrays"
243+ assert $ NEA .union (fromArray [1 , 2 , 3 ]) (fromArray [2 , 3 , 4 ]) == fromArray [1 , 2 , 3 , 4 ]
244+ assert $ NEA .union (fromArray [1 , 1 , 2 , 3 ]) (fromArray [2 , 3 , 4 ]) == fromArray [1 , 1 , 2 , 3 , 4 ]
245+
246+ log " unionBy should produce the union of two arrays using the specified equality relation"
247+ assert $ NEA .unionBy (\_ y -> y < 5 ) (fromArray [1 , 2 , 3 ]) (fromArray [2 , 3 , 4 , 5 , 6 ]) == fromArray [1 , 2 , 3 , 5 , 6 ]
248+
249+ log " delete should remove the first matching item from an array"
250+ assert $ NEA .delete 1 (fromArray [1 , 2 , 1 ]) == [2 , 1 ]
251+ assert $ NEA .delete 2 (fromArray [1 , 2 , 1 ]) == [1 , 1 ]
252+
253+ log " deleteBy should remove the first equality-relation-matching item from an array"
254+ assert $ NEA .deleteBy (/=) 2 (fromArray [1 , 2 , 1 ]) == [2 , 1 ]
255+ assert $ NEA .deleteBy (/=) 1 (fromArray [1 , 2 , 1 ]) == [1 , 1 ]
256+
257+ log " intersect should return the intersection of two arrays"
258+ assert $ NEA .intersect (fromArray [1 , 2 , 3 , 4 , 3 , 2 , 1 ]) (fromArray [1 , 1 , 2 , 3 ]) == [1 , 2 , 3 , 3 , 2 , 1 ]
259+
260+ log " intersectBy should return the intersection of two arrays using the specified equivalence relation"
261+ assert $ NEA .intersectBy (\x y -> (x * 2 ) == y) (fromArray [1 , 2 , 3 ]) (fromArray [2 , 6 ]) == [1 , 3 ]
262+
263+ log " zipWith should use the specified function to zip two arrays together"
264+ assert $ NEA .zipWith (\x y -> [show x, y]) (fromArray [1 , 2 , 3 ]) (fromArray [" a" , " b" , " c" ]) == fromArray [[" 1" , " a" ], [" 2" , " b" ], [" 3" , " c" ]]
265+
266+ log " zipWithA should use the specified function to zip two lists together"
267+ assert $ NEA .zipWithA (\x y -> Just $ Tuple x y) (fromArray [1 , 2 , 3 ]) (fromArray [" a" , " b" , " c" ]) == Just (fromArray [Tuple 1 " a" , Tuple 2 " b" , Tuple 3 " c" ])
268+
269+ log " zip should use the specified function to zip two lists together"
270+ assert $ NEA .zip (fromArray [1 , 2 , 3 ]) (fromArray [" a" , " b" , " c" ]) == fromArray [Tuple 1 " a" , Tuple 2 " b" , Tuple 3 " c" ]
271+
272+ log " unzip should deconstruct a list of tuples into a tuple of lists"
273+ assert $ NEA .unzip (fromArray [Tuple 1 " a" , Tuple 2 " b" , Tuple 3 " c" ]) == Tuple (fromArray [1 , 2 , 3 ]) (fromArray [" a" , " b" , " c" ])
274+
275+ log " fromFoldable"
276+ for_ (fromArray [[] , [1 ], [1 ,2 ], [1 ,2 ,3 ,4 ,5 ]] ) \xs -> do
277+ assert $ NEA .fromFoldable xs == NEA .fromArray xs
278+
279+ log " toUnfoldable"
280+ let toUnfoldableId xs = NEA .toUnfoldable xs == NEA .toArray xs
281+ traverse_ (assert <<< toUnfoldableId) $
282+ fromArray (
283+ [ fromArray [1 ]
284+ , fromArray [1 ,2 ,3 ]
285+ , fromArray [2 ,3 ,1 ]
286+ , fromArray [4 ,0 ,0 ,1 ,25 ,36 ,458 ,5842 ,23757 ]
287+ ])
38288
39289 log " foldl should work"
40290 -- test through sum
41- assert $ sum (unsafePartial fromJust ( NEA . fromArray [1 , 2 , 3 , 4 ]) ) == 10
291+ assert $ sum (fromArray [1 , 2 , 3 , 4 ]) == 10
42292
43293 log " foldMap1 should work"
44- assert $ foldMap1 Additive (unsafePartial fromJust ( NEA . fromArray [1 , 2 , 3 , 4 ]) ) == Additive 10
294+ assert $ foldMap1 Additive (fromArray [1 , 2 , 3 , 4 ]) == Additive 10
45295
46296 log " traverse1 should work"
47- assert $ traverse1 Just (unsafePartial fromJust (NEA .fromArray [1 , 2 , 3 , 4 ])) == NEA .fromArray [1 , 2 , 3 , 4 ]
297+ assert $ traverse1 Just (fromArray [1 , 2 , 3 , 4 ]) == NEA .fromArray [1 , 2 , 3 , 4 ]
298+
299+ odd :: Int -> Boolean
300+ odd n = n `mod` 2 /= zero
301+
302+ doubleAndOrig :: Int -> NEA.NonEmptyArray Int
303+ doubleAndOrig x = NEA .cons (x * 2 ) (NEA .singleton x)
0 commit comments