Skip to content

Commit ad31f0a

Browse files
authored
Merge pull request #151 from cryogenian/with-index
added FunctorWithIndex, FoldableWithIndex, TraversableWithIndex insta…
2 parents 61e9c15 + 8fb5017 commit ad31f0a

File tree

6 files changed

+74
-10
lines changed

6 files changed

+74
-10
lines changed

src/Data/List/Lazy/Types.purs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ import Control.MonadZero (class MonadZero)
1212
import Control.Plus (class Plus)
1313
import Data.Eq (class Eq1, eq1)
1414
import Data.Foldable (class Foldable, foldMap, foldl, foldr)
15-
import Data.FoldableWithIndex (class FoldableWithIndex, foldlWithIndex, foldrWithIndex)
16-
import Data.FunctorWithIndex (class FunctorWithIndex)
15+
import Data.FoldableWithIndex (class FoldableWithIndex, foldlWithIndex, foldrWithIndex, foldMapWithIndex)
16+
import Data.FunctorWithIndex (class FunctorWithIndex, mapWithIndex)
1717
import Data.Lazy (Lazy, defer, force)
18-
import Data.Maybe (Maybe(..))
18+
import Data.Maybe (Maybe(..), maybe)
1919
import Data.Newtype (class Newtype, unwrap)
2020
import Data.NonEmpty (NonEmpty, (:|))
2121
import Data.NonEmpty as NE
2222
import Data.Ord (class Ord1, compare1)
2323
import Data.Traversable (class Traversable, traverse, sequence)
24-
import Data.TraversableWithIndex (class TraversableWithIndex)
24+
import Data.TraversableWithIndex (class TraversableWithIndex, traverseWithIndex)
2525
import Data.Tuple (Tuple(..), snd)
2626
import Data.Unfoldable (class Unfoldable)
2727
import Data.Unfoldable1 (class Unfoldable1)
@@ -269,3 +269,15 @@ instance traversableNonEmptyList :: Traversable NonEmptyList where
269269
map (\xxs -> NonEmptyList $ defer \_ -> xxs) $ traverse f (force nel)
270270
sequence (NonEmptyList nel) =
271271
map (\xxs -> NonEmptyList $ defer \_ -> xxs) $ sequence (force nel)
272+
273+
instance functorWithIndexNonEmptyList :: FunctorWithIndex Int NonEmptyList where
274+
mapWithIndex f (NonEmptyList ne) = NonEmptyList $ defer \_ -> mapWithIndex (f <<< maybe 0 (add 1)) $ force ne
275+
276+
instance foldableWithIndexNonEmptyList :: FoldableWithIndex Int NonEmptyList where
277+
foldMapWithIndex f (NonEmptyList ne) = foldMapWithIndex (f <<< maybe 0 (add 1)) $ force ne
278+
foldlWithIndex f b (NonEmptyList ne) = foldlWithIndex (f <<< maybe 0 (add 1)) b $ force ne
279+
foldrWithIndex f b (NonEmptyList ne) = foldrWithIndex (f <<< maybe 0 (add 1)) b $ force ne
280+
281+
instance traversableWithIndexNonEmptyList :: TraversableWithIndex Int NonEmptyList where
282+
traverseWithIndex f (NonEmptyList ne) =
283+
map (\xxs -> NonEmptyList $ defer \_ -> xxs) $ traverseWithIndex (f <<< maybe 0 (add 1)) $ force ne

src/Data/List/NonEmpty.purs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ module Data.List.NonEmpty
5959
import Prelude
6060

6161
import Data.Foldable (class Foldable)
62+
import Data.FunctorWithIndex (mapWithIndex) as FWI
6263
import Data.List ((:))
6364
import Data.List as L
6465
import Data.List.Types (NonEmptyList(..))
@@ -219,8 +220,11 @@ appendFoldable :: forall t a. Foldable t => NonEmptyList a -> t a -> NonEmptyLis
219220
appendFoldable (NonEmptyList (x :| xs)) ys =
220221
NonEmptyList (x :| (xs <> L.fromFoldable ys))
221222

223+
-- | Apply a function to each element and its index in a list starting at 0.
224+
-- |
225+
-- | Deprecated. Use Data.FunctorWithIndex instead.
222226
mapWithIndex :: forall a b. (Int -> a -> b) -> NonEmptyList a -> NonEmptyList b
223-
mapWithIndex = wrappedOperation "mapWithIndex" <<< L.mapWithIndex
227+
mapWithIndex = FWI.mapWithIndex
224228

225229
sort :: forall a. Ord a => NonEmptyList a -> NonEmptyList a
226230
sort xs = sortBy compare xs

src/Data/List/Types.purs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@ import Control.MonadZero (class MonadZero)
1212
import Control.Plus (class Plus)
1313
import Data.Eq (class Eq1, eq1)
1414
import Data.Foldable (class Foldable, foldl, foldr, intercalate)
15-
import Data.FoldableWithIndex (class FoldableWithIndex, foldlWithIndex, foldrWithIndex)
16-
import Data.FunctorWithIndex (class FunctorWithIndex)
17-
import Data.Maybe (Maybe(..))
15+
import Data.FoldableWithIndex (class FoldableWithIndex, foldlWithIndex, foldrWithIndex, foldMapWithIndex)
16+
import Data.FunctorWithIndex (class FunctorWithIndex, mapWithIndex)
17+
import Data.Maybe (Maybe(..), maybe)
1818
import Data.Newtype (class Newtype)
1919
import Data.NonEmpty (NonEmpty, (:|))
2020
import Data.NonEmpty as NE
2121
import Data.Ord (class Ord1, compare1)
2222
import Data.Semigroup.Foldable (class Foldable1)
2323
import Data.Semigroup.Traversable (class Traversable1, traverse1)
2424
import Data.Traversable (class Traversable, traverse)
25-
import Data.TraversableWithIndex (class TraversableWithIndex)
25+
import Data.TraversableWithIndex (class TraversableWithIndex, traverseWithIndex)
2626
import Data.Tuple (Tuple(..), snd)
2727
import Data.Unfoldable (class Unfoldable)
2828
import Data.Unfoldable1 (class Unfoldable1)
@@ -213,6 +213,17 @@ derive newtype instance traversableNonEmptyList :: Traversable NonEmptyList
213213

214214
derive newtype instance foldable1NonEmptyList :: Foldable1 NonEmptyList
215215

216+
instance functorWithIndexNonEmptyList :: FunctorWithIndex Int NonEmptyList where
217+
mapWithIndex fn (NonEmptyList ne) = NonEmptyList $ mapWithIndex (fn <<< maybe 0 (add 1)) ne
218+
219+
instance foldableWithIndexNonEmptyList :: FoldableWithIndex Int NonEmptyList where
220+
foldMapWithIndex f (NonEmptyList ne) = foldMapWithIndex (f <<< maybe 0 (add 1)) ne
221+
foldlWithIndex f b (NonEmptyList ne) = foldlWithIndex (f <<< maybe 0 (add 1)) b ne
222+
foldrWithIndex f b (NonEmptyList ne) = foldrWithIndex (f <<< maybe 0 (add 1)) b ne
223+
224+
instance traversableWithIndexNonEmptyList :: TraversableWithIndex Int NonEmptyList where
225+
traverseWithIndex f (NonEmptyList ne) = NonEmptyList <$> traverseWithIndex (f <<< maybe 0 (add 1)) ne
226+
216227
instance traversable1NonEmptyList :: Traversable1 NonEmptyList where
217228
traverse1 f (NonEmptyList (a :| as)) =
218229
foldl (\acc -> lift2 (flip nelCons) acc <<< f) (pure <$> f a) as

test/Test/Data/List.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ testList = do
217217
assert $ catMaybes (l [Nothing, Just 2, Nothing, Just 4]) == l [2, 4]
218218

219219
log "mapWithIndex should take a list of values and apply a function which also takes the index into account"
220-
assert $ mapWithIndex (\x ix -> x + ix) (fromFoldable [0, 1, 2, 3]) == fromFoldable [0, 2, 4, 6]
220+
assert $ mapWithIndex (\x ix -> x + ix) (l [0, 1, 2, 3]) == l [0, 2, 4, 6]
221221

222222
log "sort should reorder a list into ascending order based on the result of compare"
223223
assert $ sort (l [1, 3, 2, 5, 6, 4]) == l [1, 2, 3, 4, 5, 6]

test/Test/Data/List/Lazy.purs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,31 +52,40 @@ testListLazy = do
5252

5353
log "foldlWithIndex should be correct"
5454
assert $ foldlWithIndex (\i b _ -> i + b) 0 (range 0 10000) == 50005000
55+
assert $ map (foldlWithIndex (\i b _ -> i + b) 0) (NEL.fromFoldable (range 0 10000)) == Just 50005000
5556

5657
log "foldlWithIndex should be stack-safe"
5758
void $ pure $ foldlWithIndex (\i b _ -> i + b) 0 $ range 0 100000
59+
void $ pure $ map (foldlWithIndex (\i b _ -> i + b) 0) $ NEL.fromFoldable $ range 0 100000
5860

5961
log "foldrWithIndex should be correct"
6062
assert $ foldrWithIndex (\i _ b -> i + b) 0 (range 0 10000) == 50005000
63+
assert $ map (foldrWithIndex (\i _ b -> i + b) 0) (NEL.fromFoldable (range 0 10000)) == Just 50005000
6164

6265
log "foldrWithIndex should be stack-safe"
6366
void $ pure $ foldrWithIndex (\i _ b -> i + b) 0 $ range 0 100000
67+
void $ pure $ map (foldrWithIndex (\i _ b -> i + b) 0) $ NEL.fromFoldable $ range 0 100000
6468

6569
log "foldMapWithIndex should be stack-safe"
6670
void $ pure $ foldMapWithIndex (\i _ -> Additive i) $ range 1 100000
71+
void $ pure $ map (foldMapWithIndex (\i _ -> Additive i)) $ NEL.fromFoldable $ range 1 100000
6772

6873
log "foldMapWithIndex should be left-to-right"
6974
assert $ foldMapWithIndex (\i _ -> show i) (fromFoldable [0, 0, 0]) == "012"
75+
assert $ map (foldMapWithIndex (\i _ -> show i)) (NEL.fromFoldable [0, 0, 0]) == Just "012"
7076

7177
log "traverse should be stack-safe"
7278
assert $ ((traverse Just longList) >>= last) == last longList
7379

7480
log "traverseWithIndex should be stack-safe"
7581
assert $ traverseWithIndex (const Just) longList == Just longList
82+
assert $ traverseWithIndex (const Just) (NEL.fromFoldable longList) == Just (NEL.fromFoldable longList)
7683

7784
log "traverseWithIndex should be correct"
7885
assert $ traverseWithIndex (\i a -> Just $ i + a) (fromFoldable [2, 2, 2])
7986
== Just (fromFoldable [2, 3, 4])
87+
assert $ map (traverseWithIndex (\i a -> Just $ i + a)) (NEL.fromFoldable [2, 2, 2])
88+
== Just (NEL.fromFoldable [2, 3, 4])
8089

8190
log "bind should be stack-safe"
8291
void $ pure $ last $ longList >>= pure
@@ -257,6 +266,7 @@ testListLazy = do
257266

258267
log "mapWithIndex should take a list of values and apply a function which also takes the index into account"
259268
assert $ mapWithIndex (\x ix -> x + ix) (fromFoldable [0, 1, 2, 3]) == fromFoldable [0, 2, 4, 6]
269+
assert $ map (mapWithIndex (\x ix -> x + ix)) (NEL.fromFoldable [0, 1, 2, 3]) == NEL.fromFoldable [0, 2, 4, 6]
260270

261271
-- log "sort should reorder a list into ascending order based on the result of compare"
262272
-- assert $ sort (l [1, 3, 2, 5, 6, 4]) == l [1, 2, 3, 4, 5, 6]

test/Test/Data/List/NonEmpty.purs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import Prelude
55
import Effect (Effect)
66
import Effect.Console (log)
77
import Data.Foldable (class Foldable, foldM, foldMap, foldl, length)
8+
import Data.FoldableWithIndex (foldlWithIndex, foldrWithIndex, foldMapWithIndex)
9+
import Data.TraversableWithIndex (traverseWithIndex)
810
import Data.List as L
911
import Data.List.NonEmpty as NEL
1012
import Data.Maybe (Maybe(..))
@@ -238,6 +240,31 @@ testNonEmptyList = do
238240
log "append should be stack-safe"
239241
void $ pure $ xs <> xs
240242

243+
log "foldlWithIndex should be correct"
244+
assert $ (foldlWithIndex (\i b _ -> i + b) 0 <$> (NEL.fromFoldable (L.range 0 10000))) == Just 50005000
245+
246+
log "foldlWithIndex should be stack-safe"
247+
void $ pure $ map (foldlWithIndex (\i b _ -> i + b) 0) $ NEL.fromFoldable $ L.range 0 100000
248+
249+
log "foldrWithIndex should be correct"
250+
assert $ (foldrWithIndex (\i _ b -> i + b) 0 <$> (NEL.fromFoldable (L.range 0 10000))) == Just 50005000
251+
252+
log "foldrWithIndex should be stack-safe"
253+
void $ pure $ map (foldrWithIndex (\i b _ -> i + b) 0) $ NEL.fromFoldable $ L.range 0 100000
254+
255+
log "foldMapWithIndex should be stack-safe"
256+
void $ pure $ map (foldMapWithIndex (\i _ -> Additive i)) $ NEL.fromFoldable $ L.range 1 100000
257+
258+
log "foldMapWithIndex should be left-to-right"
259+
assert $ map (foldMapWithIndex (\i _ -> show i)) (NEL.fromFoldable [0, 0, 0]) == Just "012"
260+
261+
log "traverseWithIndex should be stack-safe"
262+
assert $ map (traverseWithIndex (const Just)) (NEL.fromFoldable xs) == Just (NEL.fromFoldable xs)
263+
264+
log "traverseWithIndex should be correct"
265+
assert $ map (traverseWithIndex (\i a -> Just $ i + a)) (NEL.fromFoldable [2, 2, 2])
266+
== Just (NEL.fromFoldable [2, 3, 4])
267+
241268
odd :: Int -> Boolean
242269
odd n = n `mod` 2 /= zero
243270

0 commit comments

Comments
 (0)