[Git][ghc/ghc][master] base: Add inits1 and tails1 to Data.List

Marge Bot (@marge-bot) gitlab at gitlab.haskell.org
Sat Jun 22 14:41:27 UTC 2024



Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC


Commits:
21fc180b by Ryan Hendrickson at 2024-06-22T10:40:55-04:00
base: Add inits1 and tails1 to Data.List

- - - - -


14 changed files:

- libraries/base/changelog.md
- libraries/base/src/Data/List.hs
- libraries/base/src/Data/List/NonEmpty.hs
- libraries/ghc-internal/ghc-internal.cabal
- + libraries/ghc-internal/src/GHC/Internal/Data/List/NonEmpty.hs
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/base-exports.stdout-ws-32
- + testsuite/tests/lib/base/InitsTails.hs
- + testsuite/tests/lib/base/InitsTails.stdout
- testsuite/tests/lib/base/all.T
- utils/haddock/html-test/ref/Identifiers.html
- utils/haddock/html-test/ref/Instances.html


Changes:

=====================================
libraries/base/changelog.md
=====================================
@@ -8,6 +8,7 @@
   * The `HasField` class now supports representation polymorphism ([CLC proposal #194](https://github.com/haskell/core-libraries-committee/issues/194))
   * Make `read` accept binary integer notation ([CLC proposal #177](https://github.com/haskell/core-libraries-committee/issues/177))
   * Improve the performance of `Data.List.sort` using an improved merging strategy. Instead of `compare`, `sort` now uses `(>)` which may break *malformed* `Ord` instances ([CLC proposal #236](https://github.com/haskell/core-libraries-committee/issues/236))
+  * Add `inits1` and `tails1` to `Data.List`, factored from the corresponding functions in `Data.List.NonEmpty` ([CLC proposal #252](https://github.com/haskell/core-libraries-committee/issues/252))
   * Add `firstA` and `secondA` to `Data.Bitraversable`. ([CLC proposal #172](https://github.com/haskell/core-libraries-committee/issues/172))
 
 ## 4.20.0.0 *TBA*


=====================================
libraries/base/src/Data/List.hs
=====================================
@@ -83,7 +83,9 @@ module Data.List
      stripPrefix,
      group,
      inits,
+     inits1,
      tails,
+     tails1,
      -- **  Predicates
      isPrefixOf,
      isSuffixOf,
@@ -177,3 +179,67 @@ module Data.List
      ) where
 
 import GHC.Internal.Data.List
+import GHC.Internal.Data.List.NonEmpty (NonEmpty(..))
+import GHC.List (build)
+
+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)


=====================================
libraries/base/src/Data/List/NonEmpty.hs
=====================================
@@ -109,10 +109,10 @@ import           Prelude             hiding (break, cycle, drop, dropWhile,
 import qualified Prelude
 
 import           Control.Applicative (Applicative (..), Alternative (many))
+import qualified Data.List                        as List
 import           GHC.Internal.Data.Foldable       hiding (length, toList)
 import qualified GHC.Internal.Data.Foldable       as Foldable
 import           GHC.Internal.Data.Function       (on)
-import qualified GHC.Internal.Data.List           as List
 import           GHC.Internal.Data.Ord            (comparing)
 import           GHC.Internal.Base            (NonEmpty(..))
 import           GHC.Internal.Stack.Types     (HasCallStack)
@@ -273,15 +273,7 @@ inits = fromList . List.inits . Foldable.toList
 --
 -- @since 4.18
 inits1 :: NonEmpty a -> NonEmpty (NonEmpty a)
-inits1 =
-  -- fromList is an unsafe function, but this usage should be safe, since:
-  -- * `inits xs = [[], ..., init (init xs), init xs, xs]`
-  -- * If `xs` is nonempty, it follows that `inits xs` contains at least one nonempty
-  --   list, since `last (inits xs) = xs`.
-  -- * The only empty element of `inits xs` is the first one (by the definition of `inits`)
-  -- * Therefore, if we take all but the first element of `inits xs` i.e.
-  --   `tail (inits xs)`, we have a nonempty list of nonempty lists
-  fromList . Prelude.map fromList . List.drop 1 . List.inits . Foldable.toList
+inits1 = fromList . List.inits1 . Foldable.toList
 
 -- | The 'tails' function takes a stream @xs@ and returns all the
 -- suffixes of @xs@, starting with the longest. The result is 'NonEmpty'
@@ -301,15 +293,7 @@ tails = fromList . List.tails . Foldable.toList
 --
 -- @since 4.18
 tails1 :: NonEmpty a -> NonEmpty (NonEmpty a)
-tails1 =
-  -- fromList is an unsafe function, but this usage should be safe, since:
-  -- * `tails xs = [xs, tail xs, tail (tail xs), ..., []]`
-  -- * If `xs` is nonempty, it follows that `tails xs` contains at least one nonempty
-  --   list, since `head (tails xs) = xs`.
-  -- * The only empty element of `tails xs` is the last one (by the definition of `tails`)
-  -- * Therefore, if we take all but the last element of `tails xs` i.e.
-  --   `init (tails xs)`, we have a nonempty list of nonempty lists
-  fromList . Prelude.map fromList . List.init . List.tails . Foldable.toList
+tails1 = fromList . List.tails1 . Foldable.toList
 
 -- | @'insert' x xs@ inserts @x@ into the last position in @xs@ where it
 -- is still less than or equal to the next element. In particular, if the


=====================================
libraries/ghc-internal/ghc-internal.cabal
=====================================
@@ -122,6 +122,7 @@ Library
         GHC.Internal.Data.IORef
         GHC.Internal.Data.Ix
         GHC.Internal.Data.List
+        GHC.Internal.Data.List.NonEmpty
         GHC.Internal.Data.Maybe
         GHC.Internal.Data.Monoid
         GHC.Internal.Data.OldList


=====================================
libraries/ghc-internal/src/GHC/Internal/Data/List/NonEmpty.hs
=====================================
@@ -0,0 +1,7 @@
+{-# LANGUAGE Trustworthy #-}
+
+module GHC.Internal.Data.List.NonEmpty
+  ( NonEmpty(..)
+  ) where
+
+import GHC.Internal.Base


=====================================
testsuite/tests/interface-stability/base-exports.stdout
=====================================
@@ -1332,6 +1332,7 @@ module Data.List where
   head :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> a
   init :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> [a]
   inits :: forall a. [a] -> [[a]]
+  inits1 :: forall a. [a] -> [GHC.Internal.Base.NonEmpty a]
   insert :: forall a. GHC.Classes.Ord a => a -> [a] -> [a]
   insertBy :: forall a. (a -> a -> GHC.Types.Ordering) -> a -> [a] -> [a]
   intercalate :: forall a. [a] -> [[a]] -> [a]
@@ -1382,6 +1383,7 @@ module Data.List where
   sum :: forall (t :: * -> *) a. (GHC.Internal.Data.Foldable.Foldable t, GHC.Internal.Num.Num a) => t a -> a
   tail :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> [a]
   tails :: forall a. [a] -> [[a]]
+  tails1 :: forall a. [a] -> [GHC.Internal.Base.NonEmpty a]
   take :: forall a. GHC.Types.Int -> [a] -> [a]
   takeWhile :: forall a. (a -> GHC.Types.Bool) -> [a] -> [a]
   transpose :: forall a. [[a]] -> [[a]]


=====================================
testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
=====================================
@@ -1332,6 +1332,7 @@ module Data.List where
   head :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> a
   init :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> [a]
   inits :: forall a. [a] -> [[a]]
+  inits1 :: forall a. [a] -> [GHC.Internal.Base.NonEmpty a]
   insert :: forall a. GHC.Classes.Ord a => a -> [a] -> [a]
   insertBy :: forall a. (a -> a -> GHC.Types.Ordering) -> a -> [a] -> [a]
   intercalate :: forall a. [a] -> [[a]] -> [a]
@@ -1382,6 +1383,7 @@ module Data.List where
   sum :: forall (t :: * -> *) a. (GHC.Internal.Data.Foldable.Foldable t, GHC.Internal.Num.Num a) => t a -> a
   tail :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> [a]
   tails :: forall a. [a] -> [[a]]
+  tails1 :: forall a. [a] -> [GHC.Internal.Base.NonEmpty a]
   take :: forall a. GHC.Types.Int -> [a] -> [a]
   takeWhile :: forall a. (a -> GHC.Types.Bool) -> [a] -> [a]
   transpose :: forall a. [[a]] -> [[a]]


=====================================
testsuite/tests/interface-stability/base-exports.stdout-mingw32
=====================================
@@ -1332,6 +1332,7 @@ module Data.List where
   head :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> a
   init :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> [a]
   inits :: forall a. [a] -> [[a]]
+  inits1 :: forall a. [a] -> [GHC.Internal.Base.NonEmpty a]
   insert :: forall a. GHC.Classes.Ord a => a -> [a] -> [a]
   insertBy :: forall a. (a -> a -> GHC.Types.Ordering) -> a -> [a] -> [a]
   intercalate :: forall a. [a] -> [[a]] -> [a]
@@ -1382,6 +1383,7 @@ module Data.List where
   sum :: forall (t :: * -> *) a. (GHC.Internal.Data.Foldable.Foldable t, GHC.Internal.Num.Num a) => t a -> a
   tail :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> [a]
   tails :: forall a. [a] -> [[a]]
+  tails1 :: forall a. [a] -> [GHC.Internal.Base.NonEmpty a]
   take :: forall a. GHC.Types.Int -> [a] -> [a]
   takeWhile :: forall a. (a -> GHC.Types.Bool) -> [a] -> [a]
   transpose :: forall a. [[a]] -> [[a]]


=====================================
testsuite/tests/interface-stability/base-exports.stdout-ws-32
=====================================
@@ -1332,6 +1332,7 @@ module Data.List where
   head :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> a
   init :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> [a]
   inits :: forall a. [a] -> [[a]]
+  inits1 :: forall a. [a] -> [GHC.Internal.Base.NonEmpty a]
   insert :: forall a. GHC.Classes.Ord a => a -> [a] -> [a]
   insertBy :: forall a. (a -> a -> GHC.Types.Ordering) -> a -> [a] -> [a]
   intercalate :: forall a. [a] -> [[a]] -> [a]
@@ -1382,6 +1383,7 @@ module Data.List where
   sum :: forall (t :: * -> *) a. (GHC.Internal.Data.Foldable.Foldable t, GHC.Internal.Num.Num a) => t a -> a
   tail :: forall a. GHC.Internal.Stack.Types.HasCallStack => [a] -> [a]
   tails :: forall a. [a] -> [[a]]
+  tails1 :: forall a. [a] -> [GHC.Internal.Base.NonEmpty a]
   take :: forall a. GHC.Types.Int -> [a] -> [a]
   takeWhile :: forall a. (a -> GHC.Types.Bool) -> [a] -> [a]
   transpose :: forall a. [[a]] -> [[a]]


=====================================
testsuite/tests/lib/base/InitsTails.hs
=====================================
@@ -0,0 +1,23 @@
+module Main (main) where
+
+import Data.List (inits, inits1, tails, tails1)
+
+main :: IO ()
+main = do
+  print $ inits "abc"
+  print $ inits ([] :: [Int])
+  print $ take 5 $ inits [1..]
+  print $ take 3 $ inits ([1, 2] ++ undefined)
+
+  print $ inits1 "abc"
+  print $ inits1 ([] :: [Int])
+  print $ take 3 $ inits1 [1..]
+  print $ take 2 $ inits1 ([1, 2] ++ undefined)
+
+  print $ tails "abc"
+  print $ tails ([] :: [Int])
+  print $ drop 1 (tails [undefined, 1, 2])
+
+  print $ tails1 "abc"
+  print $ tails1 ([] :: [Int])
+  print $ drop 1 (tails1 [undefined, 1, 2])


=====================================
testsuite/tests/lib/base/InitsTails.stdout
=====================================
@@ -0,0 +1,14 @@
+["","a","ab","abc"]
+[[]]
+[[],[1],[1,2],[1,2,3],[1,2,3,4]]
+[[],[1],[1,2]]
+['a' :| "",'a' :| "b",'a' :| "bc"]
+[]
+[1 :| [],1 :| [2],1 :| [2,3]]
+[1 :| [],1 :| [2]]
+["abc","bc","c",""]
+[[]]
+[[1,2],[2],[]]
+['a' :| "bc",'b' :| "c",'c' :| ""]
+[]
+[1 :| [2],2 :| []]


=====================================
testsuite/tests/lib/base/all.T
=====================================
@@ -12,3 +12,4 @@ test('Unsnoc', normal, compile_and_run, [''])
 test('First-Semigroup-sconcat', normal, compile_and_run, [''])
 test('First-Monoid-sconcat', normal, compile_and_run, [''])
 test('Sort', normal, compile_and_run, [''])
+test('InitsTails', normal, compile_and_run, [''])


=====================================
utils/haddock/html-test/ref/Identifiers.html
=====================================
@@ -142,7 +142,7 @@
 		><ul
 		><li
 		  >Unqualified: <code
-		    ><a href="#" title="Data.List"
+		    ><a href="#" title="GHC.List"
 		      >++</a
 		      ></code
 		    >, <code
@@ -162,7 +162,7 @@
 		    ></li
 		  ><li
 		  >Namespaced: <code
-		    ><a href="#" title="Data.List"
+		    ><a href="#" title="GHC.List"
 		      >++</a
 		      ></code
 		    >, <code class="inline-code"
@@ -199,7 +199,7 @@
 		><li
 		  >Unqualified: <code class="inline-code"
 		    ><code
-		      ><a href="#" title="Data.List"
+		      ><a href="#" title="GHC.List"
 			>(++)</a
 			></code
 		      > [1,2,3] [4,5,6]</code
@@ -214,7 +214,7 @@
 		    ></li
 		  ><li
 		  >Namespaced: <code
-		    ><a href="#" title="Data.List"
+		    ><a href="#" title="GHC.List"
 		      >(++)</a
 		      ></code
 		    >, <code class="inline-code"


=====================================
utils/haddock/html-test/ref/Instances.html
=====================================
@@ -266,7 +266,7 @@
 		      ></span
 		      > <a href="#" title="Instances"
 		      >Foo</a
-		      > <a href="#" title="Data.List"
+		      > <a href="#" title="GHC.Exts"
 		      >[]</a
 		      ></span
 		    > <a href="#" class="selflink"
@@ -910,7 +910,7 @@
 		      ></span
 		      > <a href="#" title="Instances"
 		      >Bar</a
-		      > <a href="#" title="Data.List"
+		      > <a href="#" title="GHC.Exts"
 		      >[]</a
 		      > (a, a)</span
 		    > <a href="#" class="selflink"



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/21fc180bec93d964a7f4ffdf2429ef6f74b49ab6

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/21fc180bec93d964a7f4ffdf2429ef6f74b49ab6
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20240622/2cdcb075/attachment-0001.html>


More information about the ghc-commits mailing list