Skip to content

Commit

Permalink
Backport inits1 and tails1 to Data.List.Compat
Browse files Browse the repository at this point in the history
Towards #97.
  • Loading branch information
RyanGlScott committed Dec 3, 2024
1 parent f92b438 commit ead5712
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 0 deletions.
1 change: 1 addition & 0 deletions base-compat/CHANGES.markdown
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Changes in next [????.??.??]
- Sync with `base-4.21`/GHC 9.12
- Backport `inits1` and `tails1` to `Data.List.Compat`
- Backport `firstA` and `secondA` to `Data.Bitraversable.Compat`
- Drop support for pre-8.0 versions of GHC.

Expand Down
1 change: 1 addition & 0 deletions base-compat/README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ So far the following is covered.
* `modifyIORef'`, `atomicModifyIORef'` and `atomicWriteIORef` to `Data.IORef.Compat`
* `dropWhileEnd`, `isSubsequenceOf`, `sortOn`, and `uncons` functions to `Data.List.Compat`
* Correct versions of `nub`, `nubBy`, `union`, and `unionBy` to `Data.List.Compat`
* `inits1` and `tails1` to `Data.List.Compat`
* `asProxyTypeOf` with a generalized type signature to `Data.Proxy.Compat`
* `modifySTRef'` to `Data.STRef.Compat`
* `String`, `lines`, `words`, `unlines`, and `unwords` to `Data.String.Compat`
Expand Down
74 changes: 74 additions & 0 deletions base-compat/src/Data/List/Compat.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
module Data.List.Compat (
module Base

#if !(MIN_VERSION_base(4,21,0))
, inits1
, tails1
#endif

#if MIN_VERSION_base(4,18,0) && !(MIN_VERSION_base(4,20,0))
, List
#endif
Expand Down Expand Up @@ -36,6 +41,11 @@ import Prelude.Compat hiding (foldr, null)
import GHC.List (List)
#endif

#if !(MIN_VERSION_base(4,21,0))
import Data.List.NonEmpty (NonEmpty(..))
import GHC.List (build)
#endif

#if !(MIN_VERSION_base(4,11,0))
-- | 'iterate\'' is the strict version of 'iterate'.
--
Expand Down Expand Up @@ -133,3 +143,67 @@ unsnoc :: [a] -> Maybe ([a], a)
unsnoc = foldr (\x -> Just . maybe ([], x) (\(~(a, b)) -> (x : a, b))) Nothing
{-# INLINABLE unsnoc #-}
#endif

#if !(MIN_VERSION_base(4,21,0))
inits1, tails1 :: [a] -> [NonEmpty a]

-- | The 'inits1' function returns all non-empty initial segments of the
-- argument, shortest first.
--
-- @since 4.21.0.0
--
-- ==== __Laziness__
--
-- Note that 'inits1' has the following strictness property:
-- @inits1 (xs ++ _|_) = inits1 xs ++ _|_@
--
-- In particular,
-- @inits1 _|_ = _|_@
--
-- ==== __Examples__
--
-- >>> inits1 "abc"
-- ['a' :| "",'a' :| "b",'a' :| "bc"]
--
-- >>> inits1 []
-- []
--
-- inits1 is productive on infinite lists:
--
-- >>> take 3 $ inits1 [1..]
-- [1 :| [],1 :| [2],1 :| [2,3]]
inits1 [] = []
inits1 (x : xs) = map (x :|) (inits xs)

-- | \(\mathcal{O}(n)\). The 'tails1' function returns all non-empty final
-- segments of the argument, longest first.
--
-- @since 4.21.0.0
--
-- ==== __Laziness__
--
-- Note that 'tails1' has the following strictness property:
-- @tails1 _|_ = _|_@
--
-- >>> tails1 undefined
-- *** Exception: Prelude.undefined
--
-- >>> drop 1 (tails1 [undefined, 1, 2])
-- [1 :| [2],2 :| []]
--
-- ==== __Examples__
--
-- >>> tails1 "abc"
-- ['a' :| "bc",'b' :| "c",'c' :| ""]
--
-- >>> tails1 [1, 2, 3]
-- [1 :| [2,3],2 :| [3],3 :| []]
--
-- >>> tails1 []
-- []
{-# INLINABLE tails1 #-}
tails1 lst = build (\c n ->
let tails1Go [] = n
tails1Go (x : xs) = (x :| xs) `c` tails1Go xs
in tails1Go lst)
#endif

0 comments on commit ead5712

Please sign in to comment.