Skip to content

added FunctorWithIndex, FoldableWithIndex, TraversableWithIndex insta… #151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions src/Data/List/Lazy/Types.purs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ import Control.MonadZero (class MonadZero)
import Control.Plus (class Plus)
import Data.Eq (class Eq1, eq1)
import Data.Foldable (class Foldable, foldMap, foldl, foldr)
import Data.FoldableWithIndex (class FoldableWithIndex, foldlWithIndex, foldrWithIndex)
import Data.FunctorWithIndex (class FunctorWithIndex)
import Data.FoldableWithIndex (class FoldableWithIndex, foldlWithIndex, foldrWithIndex, foldMapWithIndex)
import Data.FunctorWithIndex (class FunctorWithIndex, mapWithIndex)
import Data.Lazy (Lazy, defer, force)
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..), maybe)
import Data.Newtype (class Newtype, unwrap)
import Data.NonEmpty (NonEmpty, (:|))
import Data.NonEmpty as NE
import Data.Ord (class Ord1, compare1)
import Data.Traversable (class Traversable, traverse, sequence)
import Data.TraversableWithIndex (class TraversableWithIndex)
import Data.TraversableWithIndex (class TraversableWithIndex, traverseWithIndex)
import Data.Tuple (Tuple(..), snd)
import Data.Unfoldable (class Unfoldable)
import Data.Unfoldable1 (class Unfoldable1)
Expand Down Expand Up @@ -269,3 +269,15 @@ instance traversableNonEmptyList :: Traversable NonEmptyList where
map (\xxs -> NonEmptyList $ defer \_ -> xxs) $ traverse f (force nel)
sequence (NonEmptyList nel) =
map (\xxs -> NonEmptyList $ defer \_ -> xxs) $ sequence (force nel)

instance functorWithIndexNonEmptyList :: FunctorWithIndex Int NonEmptyList where
mapWithIndex f (NonEmptyList ne) = NonEmptyList $ defer \_ -> mapWithIndex (f <<< maybe 0 (add 1)) $ force ne

instance foldableWithIndexNonEmptyList :: FoldableWithIndex Int NonEmptyList where
foldMapWithIndex f (NonEmptyList ne) = foldMapWithIndex (f <<< maybe 0 (add 1)) $ force ne
foldlWithIndex f b (NonEmptyList ne) = foldlWithIndex (f <<< maybe 0 (add 1)) b $ force ne
foldrWithIndex f b (NonEmptyList ne) = foldrWithIndex (f <<< maybe 0 (add 1)) b $ force ne

instance traversableWithIndexNonEmptyList :: TraversableWithIndex Int NonEmptyList where
traverseWithIndex f (NonEmptyList ne) =
map (\xxs -> NonEmptyList $ defer \_ -> xxs) $ traverseWithIndex (f <<< maybe 0 (add 1)) $ force ne
6 changes: 5 additions & 1 deletion src/Data/List/NonEmpty.purs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ module Data.List.NonEmpty
import Prelude

import Data.Foldable (class Foldable)
import Data.FunctorWithIndex (mapWithIndex) as FWI
import Data.List ((:))
import Data.List as L
import Data.List.Types (NonEmptyList(..))
Expand Down Expand Up @@ -219,8 +220,11 @@ appendFoldable :: forall t a. Foldable t => NonEmptyList a -> t a -> NonEmptyLis
appendFoldable (NonEmptyList (x :| xs)) ys =
NonEmptyList (x :| (xs <> L.fromFoldable ys))

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

sort :: forall a. Ord a => NonEmptyList a -> NonEmptyList a
sort xs = sortBy compare xs
Expand Down
19 changes: 15 additions & 4 deletions src/Data/List/Types.purs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ import Control.MonadZero (class MonadZero)
import Control.Plus (class Plus)
import Data.Eq (class Eq1, eq1)
import Data.Foldable (class Foldable, foldl, foldr, intercalate)
import Data.FoldableWithIndex (class FoldableWithIndex, foldlWithIndex, foldrWithIndex)
import Data.FunctorWithIndex (class FunctorWithIndex)
import Data.Maybe (Maybe(..))
import Data.FoldableWithIndex (class FoldableWithIndex, foldlWithIndex, foldrWithIndex, foldMapWithIndex)
import Data.FunctorWithIndex (class FunctorWithIndex, mapWithIndex)
import Data.Maybe (Maybe(..), maybe)
import Data.Newtype (class Newtype)
import Data.NonEmpty (NonEmpty, (:|))
import Data.NonEmpty as NE
import Data.Ord (class Ord1, compare1)
import Data.Semigroup.Foldable (class Foldable1)
import Data.Semigroup.Traversable (class Traversable1, traverse1)
import Data.Traversable (class Traversable, traverse)
import Data.TraversableWithIndex (class TraversableWithIndex)
import Data.TraversableWithIndex (class TraversableWithIndex, traverseWithIndex)
import Data.Tuple (Tuple(..), snd)
import Data.Unfoldable (class Unfoldable)
import Data.Unfoldable1 (class Unfoldable1)
Expand Down Expand Up @@ -213,6 +213,17 @@ derive newtype instance traversableNonEmptyList :: Traversable NonEmptyList

derive newtype instance foldable1NonEmptyList :: Foldable1 NonEmptyList

instance functorWithIndexNonEmptyList :: FunctorWithIndex Int NonEmptyList where
mapWithIndex fn (NonEmptyList ne) = NonEmptyList $ mapWithIndex (fn <<< maybe 0 (add 1)) ne

instance foldableWithIndexNonEmptyList :: FoldableWithIndex Int NonEmptyList where
foldMapWithIndex f (NonEmptyList ne) = foldMapWithIndex (f <<< maybe 0 (add 1)) ne
foldlWithIndex f b (NonEmptyList ne) = foldlWithIndex (f <<< maybe 0 (add 1)) b ne
foldrWithIndex f b (NonEmptyList ne) = foldrWithIndex (f <<< maybe 0 (add 1)) b ne

instance traversableWithIndexNonEmptyList :: TraversableWithIndex Int NonEmptyList where
traverseWithIndex f (NonEmptyList ne) = NonEmptyList <$> traverseWithIndex (f <<< maybe 0 (add 1)) ne

instance traversable1NonEmptyList :: Traversable1 NonEmptyList where
traverse1 f (NonEmptyList (a :| as)) =
foldl (\acc -> lift2 (flip nelCons) acc <<< f) (pure <$> f a) as
Expand Down
2 changes: 1 addition & 1 deletion test/Test/Data/List.purs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ testList = do
assert $ catMaybes (l [Nothing, Just 2, Nothing, Just 4]) == l [2, 4]

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

log "sort should reorder a list into ascending order based on the result of compare"
assert $ sort (l [1, 3, 2, 5, 6, 4]) == l [1, 2, 3, 4, 5, 6]
Expand Down
10 changes: 10 additions & 0 deletions test/Test/Data/List/Lazy.purs
Original file line number Diff line number Diff line change
Expand Up @@ -52,31 +52,40 @@ testListLazy = do

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

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

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

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

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

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

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

log "traverseWithIndex should be stack-safe"
assert $ traverseWithIndex (const Just) longList == Just longList
assert $ traverseWithIndex (const Just) (NEL.fromFoldable longList) == Just (NEL.fromFoldable longList)

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

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

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

-- log "sort should reorder a list into ascending order based on the result of compare"
-- assert $ sort (l [1, 3, 2, 5, 6, 4]) == l [1, 2, 3, 4, 5, 6]
Expand Down
27 changes: 27 additions & 0 deletions test/Test/Data/List/NonEmpty.purs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import Prelude
import Effect (Effect)
import Effect.Console (log)
import Data.Foldable (class Foldable, foldM, foldMap, foldl, length)
import Data.FoldableWithIndex (foldlWithIndex, foldrWithIndex, foldMapWithIndex)
import Data.TraversableWithIndex (traverseWithIndex)
import Data.List as L
import Data.List.NonEmpty as NEL
import Data.Maybe (Maybe(..))
Expand Down Expand Up @@ -238,6 +240,31 @@ testNonEmptyList = do
log "append should be stack-safe"
void $ pure $ xs <> xs

log "foldlWithIndex should be correct"
assert $ (foldlWithIndex (\i b _ -> i + b) 0 <$> (NEL.fromFoldable (L.range 0 10000))) == Just 50005000

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

log "foldrWithIndex should be correct"
assert $ (foldrWithIndex (\i _ b -> i + b) 0 <$> (NEL.fromFoldable (L.range 0 10000))) == Just 50005000

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

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

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

log "traverseWithIndex should be stack-safe"
assert $ map (traverseWithIndex (const Just)) (NEL.fromFoldable xs) == Just (NEL.fromFoldable xs)

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

odd :: Int -> Boolean
odd n = n `mod` 2 /= zero

Expand Down