From aeed7b3a6518b5ce6503d06e84736ee641d4c2bf Mon Sep 17 00:00:00 2001 From: UnrelatedString Date: Thu, 27 Feb 2025 16:25:04 -0500 Subject: [PATCH 1/6] my toUnfoldable(1) tweak seems to compile and pass tests in the non-Lazy NonEmpty --- src/Data/List/NonEmpty.purs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Data/List/NonEmpty.purs b/src/Data/List/NonEmpty.purs index 42fa49e..41c0e0f 100644 --- a/src/Data/List/NonEmpty.purs +++ b/src/Data/List/NonEmpty.purs @@ -71,7 +71,7 @@ import Data.NonEmpty ((:|)) import Data.NonEmpty as NE import Data.Semigroup.Traversable (sequence1) import Data.Tuple (Tuple(..), fst, snd) -import Data.Unfoldable (class Unfoldable, unfoldr) +import Data.Unfoldable1 (class Unfoldable1, unfoldr1) import Partial.Unsafe (unsafeCrashWith) import Data.Foldable (foldl, foldr, foldMap, fold, intercalate, elem, notElem, find, findMap, any, all) as Exports @@ -111,9 +111,12 @@ wrappedOperation2 name f (NonEmptyList (x :| xs)) (NonEmptyList (y :| ys)) = lift :: forall a b. (L.List a -> b) -> NonEmptyList a -> b lift f (NonEmptyList (x :| xs)) = f (x : xs) -toUnfoldable :: forall f. Unfoldable f => NonEmptyList ~> f -toUnfoldable = - unfoldr (\xs -> (\rec -> Tuple rec.head rec.tail) <$> L.uncons xs) <<< toList +toUnfoldable :: forall f. Unfoldable1 f => NonEmptyList ~> f +toUnfoldable = + unfoldr1 (\rec -> Tuple rec.head $ L.uncons rec.tail) <<< uncons + + + -- unfoldr (\xs -> (\rec -> Tuple rec.head rec.tail) <$> L.uncons xs) <<< toList fromFoldable :: forall f a. Foldable f => f a -> Maybe (NonEmptyList a) fromFoldable = fromList <<< L.fromFoldable From ae20e8876bf39fd2ba3215ed04f93932ebd59567 Mon Sep 17 00:00:00 2001 From: UnrelatedString Date: Thu, 27 Feb 2025 16:26:58 -0500 Subject: [PATCH 2/6] And it seems to work copy-pasted in Data.List.Lazy.NonEmpty --- src/Data/List/Lazy/NonEmpty.purs | 6 +++--- src/Data/List/NonEmpty.purs | 5 +---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Data/List/Lazy/NonEmpty.purs b/src/Data/List/Lazy/NonEmpty.purs index d5d207d..574c510 100644 --- a/src/Data/List/Lazy/NonEmpty.purs +++ b/src/Data/List/Lazy/NonEmpty.purs @@ -28,11 +28,11 @@ import Data.List.Lazy.Types (NonEmptyList(..)) import Data.Maybe (Maybe(..), maybe, fromMaybe) import Data.NonEmpty ((:|)) import Data.Tuple (Tuple(..)) -import Data.Unfoldable (class Unfoldable, unfoldr) +import Data.Unfoldable1 (class Unfoldable1, unfoldr1) -toUnfoldable :: forall f. Unfoldable f => NonEmptyList ~> f +toUnfoldable :: forall f. Unfoldable1 f => NonEmptyList ~> f toUnfoldable = - unfoldr (\xs -> (\rec -> Tuple rec.head rec.tail) <$> L.uncons xs) <<< toList + unfoldr1 (\rec -> Tuple rec.head $ L.uncons rec.tail) <<< uncons fromFoldable :: forall f a. Foldable f => f a -> Maybe (NonEmptyList a) fromFoldable = fromList <<< L.fromFoldable diff --git a/src/Data/List/NonEmpty.purs b/src/Data/List/NonEmpty.purs index 41c0e0f..ce6c13f 100644 --- a/src/Data/List/NonEmpty.purs +++ b/src/Data/List/NonEmpty.purs @@ -112,12 +112,9 @@ lift :: forall a b. (L.List a -> b) -> NonEmptyList a -> b lift f (NonEmptyList (x :| xs)) = f (x : xs) toUnfoldable :: forall f. Unfoldable1 f => NonEmptyList ~> f -toUnfoldable = +toUnfoldable = unfoldr1 (\rec -> Tuple rec.head $ L.uncons rec.tail) <<< uncons - - -- unfoldr (\xs -> (\rec -> Tuple rec.head rec.tail) <$> L.uncons xs) <<< toList - fromFoldable :: forall f a. Foldable f => f a -> Maybe (NonEmptyList a) fromFoldable = fromList <<< L.fromFoldable From 9774982e49d73d02c4949ea18e1df0c175a0b054 Mon Sep 17 00:00:00 2001 From: UnrelatedString Date: Thu, 27 Feb 2025 16:56:35 -0500 Subject: [PATCH 3/6] Added tests for toUnfoldable (both my NonEmpty reimpls and the normal ones --- test/Test/Data/List.purs | 5 ++++- test/Test/Data/List/Lazy.purs | 14 +++++++++++++- test/Test/Data/List/NonEmpty.purs | 3 +++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/test/Test/Data/List.purs b/test/Test/Data/List.purs index a96b6d7..cbd1513 100644 --- a/test/Test/Data/List.purs +++ b/test/Test/Data/List.purs @@ -6,7 +6,7 @@ import Data.Array as Array import Data.Foldable (class Foldable, foldMap, foldl) import Data.FoldableWithIndex (foldMapWithIndex, foldlWithIndex, foldrWithIndex) import Data.Function (on) -import Data.List (List(..), Pattern(..), alterAt, catMaybes, concat, concatMap, delete, deleteAt, deleteBy, drop, dropEnd, dropWhile, elemIndex, elemLastIndex, filter, filterM, findIndex, findLastIndex, foldM, fromFoldable, group, groupAll, groupAllBy, groupBy, head, init, insert, insertAt, insertBy, intersect, intersectBy, last, length, mapMaybe, modifyAt, nub, nubBy, nubByEq, nubEq, null, partition, range, reverse, singleton, snoc, sort, sortBy, span, stripPrefix, tail, take, takeEnd, takeWhile, transpose, uncons, union, unionBy, unsnoc, unzip, updateAt, zip, zipWith, zipWithA, (!!), (..), (:), (\\)) +import Data.List (List(..), Pattern(..), alterAt, catMaybes, concat, concatMap, delete, deleteAt, deleteBy, drop, dropEnd, dropWhile, elemIndex, elemLastIndex, filter, filterM, findIndex, findLastIndex, foldM, fromFoldable, group, groupAll, groupAllBy, groupBy, head, init, insert, insertAt, insertBy, intersect, intersectBy, last, length, mapMaybe, modifyAt, nub, nubBy, nubByEq, nubEq, null, partition, range, reverse, singleton, snoc, sort, sortBy, span, stripPrefix, tail, take, takeEnd, takeWhile, toUnfoldable, transpose, uncons, union, unionBy, unsnoc, unzip, updateAt, zip, zipWith, zipWithA, (!!), (..), (:), (\\)) import Data.List.NonEmpty as NEL import Data.Maybe (Maybe(..), isNothing, fromJust) import Data.Monoid.Additive (Additive(..)) @@ -411,6 +411,9 @@ testList = do log "append should be stack-safe" void $ pure $ xs <> xs + log "toUnfoldable should agree with Unfoldable List" + assert $ (1..5) == toUnfoldable (1..5) + step :: Int -> Maybe (Tuple Int Int) step 6 = Nothing step n = Just (Tuple n (n + 1)) diff --git a/test/Test/Data/List/Lazy.purs b/test/Test/Data/List/Lazy.purs index c1c2978..4523758 100644 --- a/test/Test/Data/List/Lazy.purs +++ b/test/Test/Data/List/Lazy.purs @@ -8,7 +8,7 @@ import Data.FoldableWithIndex (foldMapWithIndex, foldlWithIndex, foldrWithIndex) import Data.Function (on) import Data.FunctorWithIndex (mapWithIndex) import Data.Lazy as Z -import Data.List.Lazy (List, Pattern(..), alterAt, catMaybes, concat, concatMap, cycle, 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, nubEq, nubByEq, null, partition, range, repeat, replicate, replicateM, reverse, scanlLazy, singleton, slice, snoc, span, stripPrefix, tail, take, takeWhile, transpose, uncons, union, unionBy, unzip, updateAt, zip, zipWith, zipWithA, (!!), (..), (:), (\\)) +import Data.List.Lazy (List, Pattern(..), alterAt, catMaybes, concat, concatMap, cycle, 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, nubEq, nubByEq, null, partition, range, repeat, replicate, replicateM, reverse, scanlLazy, singleton, slice, snoc, span, stripPrefix, tail, take, takeWhile, toUnfoldable, transpose, uncons, union, unionBy, unzip, updateAt, zip, zipWith, zipWithA, (!!), (..), (:), (\\)) import Data.List.Lazy.NonEmpty as NEL import Data.Maybe (Maybe(..), isNothing, fromJust) import Data.Monoid.Additive (Additive(..)) @@ -459,6 +459,18 @@ testListLazy = do log "unfoldr1 should maintain order for NEL" assert $ (nel (1 :| l [2, 3, 4, 5])) == unfoldr1 step1 1 + log "toUnfoldable should agree with Unfoldable List" + assert $ (1..5) == toUnfoldable (1..5) + + log "toUnfoldable should agree with Unfoldable1 NEL" + assert $ nel (1 :| (2..5)) == NEL.toUnfoldable (nel (1 :| (2..5))) + + log "toUnfoldable should work ok on infinite List" + assert $ Just 1 == toUnfoldable (iterate (_ + 1) 1) + + log "toUnfoldable should work ok on infinite NEL" + assert $ Just 1 == NEL.toUnfoldable (nel $ 1 :| iterate (_ + 1) 2) -- Bit odd that `iterate` doesn't produce a NEL as is, but I suppose the whole thing's an afterthought + step :: Int -> Maybe (Tuple Int Int) step 6 = Nothing step n = Just (Tuple n (n + 1)) diff --git a/test/Test/Data/List/NonEmpty.purs b/test/Test/Data/List/NonEmpty.purs index 6ad71c1..db087e5 100644 --- a/test/Test/Data/List/NonEmpty.purs +++ b/test/Test/Data/List/NonEmpty.purs @@ -281,6 +281,9 @@ testNonEmptyList = do log "unfoldr1 should maintain order" assert $ (nel 1 [2, 3, 4, 5]) == unfoldr1 step1 1 + log "toUnfoldable should agree with Unfoldable1 NEL" + assert $ nel 1 [2, 3, 4, 5] == NEL.toUnfoldable (nel 1 [2, 3, 4, 5]) + step1 :: Int -> Tuple Int (Maybe Int) step1 n = Tuple n (if n >= 5 then Nothing else Just (n + 1)) From e88840f36769162d3001122f94cf79996b5cceae Mon Sep 17 00:00:00 2001 From: UnrelatedString <33167175+UnrelatedString@users.noreply.github.com> Date: Thu, 27 Feb 2025 17:31:50 -0500 Subject: [PATCH 4/6] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db8662b..0f489b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ Breaking changes: New features: +- Change `NonEmpty.toUnfoldable` to produce any `Unfoldable1` (#218 by @UnrelatedString) + Bugfixes: Other improvements: From ed16fa4c564957e94cecfba6af284f74b9c907cf Mon Sep 17 00:00:00 2001 From: UnrelatedString Date: Thu, 27 Feb 2025 17:35:16 -0500 Subject: [PATCH 5/6] oh yeah, iterate IS in NonEmpty --- test/Test/Data/List/Lazy.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Test/Data/List/Lazy.purs b/test/Test/Data/List/Lazy.purs index 4523758..a57ff39 100644 --- a/test/Test/Data/List/Lazy.purs +++ b/test/Test/Data/List/Lazy.purs @@ -469,7 +469,7 @@ testListLazy = do assert $ Just 1 == toUnfoldable (iterate (_ + 1) 1) log "toUnfoldable should work ok on infinite NEL" - assert $ Just 1 == NEL.toUnfoldable (nel $ 1 :| iterate (_ + 1) 2) -- Bit odd that `iterate` doesn't produce a NEL as is, but I suppose the whole thing's an afterthought + assert $ Just 1 == NEL.toUnfoldable (NEL.iterate (_ + 1) 1) step :: Int -> Maybe (Tuple Int Int) step 6 = Nothing From 048081a579f6e1c3e54665c90b1d91e48cfb7fe0 Mon Sep 17 00:00:00 2001 From: UnrelatedString <33167175+UnrelatedString@users.noreply.github.com> Date: Thu, 27 Feb 2025 17:45:03 -0500 Subject: [PATCH 6/6] Update CHANGELOG.md Fixed my bad guess for PR name --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f489b9..cedff42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ Breaking changes: New features: -- Change `NonEmpty.toUnfoldable` to produce any `Unfoldable1` (#218 by @UnrelatedString) +- Change `NonEmpty.toUnfoldable` to produce any `Unfoldable1` (#220 by @UnrelatedString) Bugfixes: