Skip to content

Commit d44e568

Browse files
committed
Add Unfoldable1 instances for Unfoldables
1 parent e84d02e commit d44e568

File tree

4 files changed

+46
-6
lines changed

4 files changed

+46
-6
lines changed

src/Data/List/Lazy/Types.purs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import Data.Traversable (class Traversable, traverse, sequence)
2424
import Data.TraversableWithIndex (class TraversableWithIndex)
2525
import Data.Tuple (Tuple(..), snd)
2626
import Data.Unfoldable (class Unfoldable)
27+
import Data.Unfoldable1 (class Unfoldable1)
2728

2829
-- | A lazy linked list.
2930
newtype List a = List (Lazy (Step a))
@@ -140,6 +141,12 @@ instance foldableWithIndexList :: FoldableWithIndex Int List where
140141
snd <<< foldl (\(Tuple i b) a -> Tuple (i + 1) (f i b a)) (Tuple 0 acc)
141142
foldMapWithIndex f = foldlWithIndex (\i acc -> append acc <<< f i) mempty
142143

144+
instance unfoldable1List :: Unfoldable1 List where
145+
unfoldr1 = go where
146+
go f b = Z.defer \_ -> case f b of
147+
Tuple a (Just b') -> a : go f b'
148+
Tuple a Nothing -> a : nil
149+
143150
instance unfoldableList :: Unfoldable List where
144151
unfoldr = go where
145152
go f b = Z.defer \_ -> case f b of

src/Data/List/Types.purs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import Data.Traversable (class Traversable, traverse)
2525
import Data.TraversableWithIndex (class TraversableWithIndex)
2626
import Data.Tuple (Tuple(..), snd)
2727
import Data.Unfoldable (class Unfoldable)
28+
import Data.Unfoldable1 (class Unfoldable1)
2829

2930
data List a = Nil | Cons a (List a)
3031

@@ -98,6 +99,13 @@ instance foldableWithIndexList :: FoldableWithIndex Int List where
9899
snd <<< foldl (\(Tuple i b) a -> Tuple (i + 1) (f i b a)) (Tuple 0 acc)
99100
foldMapWithIndex f = foldlWithIndex (\i acc -> append acc <<< f i) mempty
100101

102+
instance unfoldable1List :: Unfoldable1 List where
103+
unfoldr1 f b = go b Nil
104+
where
105+
go source memo = case f source of
106+
Tuple one (Just rest) -> go rest (one : memo)
107+
Tuple one Nothing -> foldl (flip (:)) Nil (one : memo)
108+
101109
instance unfoldableList :: Unfoldable List where
102110
unfoldr f b = go b Nil
103111
where

test/Test/Data/List.purs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ module Test.Data.List (testList) where
22

33
import Prelude
44

5-
import Effect (Effect)
6-
import Effect.Console (log)
75
import Data.Foldable (foldMap, foldl)
86
import Data.FoldableWithIndex (foldMapWithIndex, foldlWithIndex, foldrWithIndex)
97
import Data.List (List(..), (..), stripPrefix, Pattern(..), length, range, foldM, unzip, zip, zipWithA, zipWith, intersectBy, intersect, (\\), deleteBy, delete, unionBy, union, nubBy, nub, groupBy, group', group, partition, span, dropWhile, drop, dropEnd, takeWhile, take, takeEnd, sortBy, sort, catMaybes, mapMaybe, filterM, filter, concat, concatMap, reverse, alterAt, modifyAt, updateAt, deleteAt, insertAt, findLastIndex, findIndex, elemLastIndex, elemIndex, (!!), uncons, unsnoc, init, tail, last, head, insertBy, insert, snoc, null, singleton, fromFoldable, transpose, mapWithIndex, (:))
@@ -15,6 +13,9 @@ import Data.Traversable (traverse)
1513
import Data.TraversableWithIndex (traverseWithIndex)
1614
import Data.Tuple (Tuple(..))
1715
import Data.Unfoldable (replicate, replicateA, unfoldr)
16+
import Data.Unfoldable1 (unfoldr1)
17+
import Effect (Effect)
18+
import Effect.Console (log)
1819
import Partial.Unsafe (unsafePartial)
1920
import Test.Assert (assert)
2021

@@ -357,6 +358,9 @@ testList = do
357358
log "unfoldr should maintain order"
358359
assert $ (1..5) == unfoldr step 1
359360

361+
log "unfoldr1 should maintain order"
362+
assert $ (1..5) == unfoldr1 step1 1
363+
360364
log "map should maintain order"
361365
assert $ (1..5) == map identity (1..5)
362366

@@ -388,11 +392,13 @@ testList = do
388392
log "append should be stack-safe"
389393
void $ pure $ xs <> xs
390394

391-
392395
step :: Int -> Maybe (Tuple Int Int)
393396
step 6 = Nothing
394397
step n = Just (Tuple n (n + 1))
395398

399+
step1 :: Int -> Tuple Int (Maybe Int)
400+
step1 n = Tuple n (if n >= 5 then Nothing else Just (n + 1))
401+
396402
nil :: List Int
397403
nil = Nil
398404

test/Test/Data/List/Lazy.purs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,21 @@ module Test.Data.List.Lazy (testListLazy) where
33
import Prelude
44

55
import Control.Lazy (defer)
6-
import Effect (Effect)
7-
import Effect.Console (log)
86
import Data.FoldableWithIndex (foldMapWithIndex, foldlWithIndex, foldrWithIndex)
97
import Data.FunctorWithIndex (mapWithIndex)
108
import Data.Lazy as Z
11-
import Data.List.Lazy (List, nil, stripPrefix, Pattern(..), cons, foldl, foldr, foldMap, singleton, transpose, take, iterate, filter, uncons, foldM, foldrLazy, range, unzip, zip, length, zipWithA, replicate, repeat, zipWith, intersectBy, intersect, deleteBy, delete, unionBy, union, nubBy, nub, groupBy, group, partition, span, dropWhile, drop, takeWhile, slice, catMaybes, mapMaybe, filterM, concat, concatMap, reverse, alterAt, modifyAt, updateAt, deleteAt, insertAt, findLastIndex, findIndex, elemLastIndex, elemIndex, init, tail, last, head, insertBy, insert, snoc, null, replicateM, fromFoldable, (:), (\\), (!!))
9+
import Data.List.Lazy (List, Pattern(..), alterAt, catMaybes, concat, concatMap, cons, delete, deleteAt, deleteBy, drop, dropWhile, elemIndex, elemLastIndex, filter, filterM, findIndex, findLastIndex, foldM, foldMap, foldl, foldr, foldrLazy, fromFoldable, group, groupBy, head, init, insert, insertAt, insertBy, intersect, intersectBy, iterate, last, length, mapMaybe, modifyAt, nil, nub, nubBy, null, partition, range, repeat, replicate, replicateM, reverse, singleton, slice, snoc, span, stripPrefix, tail, take, takeWhile, transpose, uncons, union, unionBy, unzip, updateAt, zip, zipWith, zipWithA, (!!), (..), (:), (\\))
1210
import Data.List.Lazy.NonEmpty as NEL
1311
import Data.Maybe (Maybe(..), isNothing, fromJust)
1412
import Data.Monoid.Additive (Additive(..))
1513
import Data.NonEmpty ((:|))
1614
import Data.Traversable (traverse)
1715
import Data.TraversableWithIndex (traverseWithIndex)
1816
import Data.Tuple (Tuple(..))
17+
import Data.Unfoldable (unfoldr)
18+
import Data.Unfoldable1 (unfoldr1)
19+
import Effect (Effect)
20+
import Effect.Console (log)
1921
import Partial.Unsafe (unsafePartial)
2022
import Test.Assert (assert)
2123

@@ -396,9 +398,26 @@ testListLazy = do
396398
((10:20:30:nil) : (11:31:nil) : (32:nil) : nil)
397399
log "transpose nil == nil"
398400
assert $ transpose nil == (nil :: List (List Int))
401+
399402
log "transpose (singleton nil) == nil"
400403
assert $ transpose (singleton nil) == (nil :: List (List Int))
401404

405+
log "unfoldr should maintain order"
406+
assert $ (1..5) == unfoldr step 1
407+
408+
log "unfoldr1 should maintain order"
409+
assert $ (1..5) == unfoldr1 step1 1
410+
411+
log "map should maintain order"
412+
assert $ (1..5) == map identity (1..5)
413+
414+
step :: Int -> Maybe (Tuple Int Int)
415+
step 6 = Nothing
416+
step n = Just (Tuple n (n + 1))
417+
418+
step1 :: Int -> Tuple Int (Maybe Int)
419+
step1 n = Tuple n (if n >= 5 then Nothing else Just (n + 1))
420+
402421
nil' :: List Int
403422
nil' = nil
404423

0 commit comments

Comments
 (0)