From 70a901105044c85c756fd93899387f0215f7b1de Mon Sep 17 00:00:00 2001
From: Julien Debon
Date: Sun, 9 Feb 2020 22:37:50 +0100
Subject: [PATCH] doc(List): Add examples to GHC.List
* Add examples
* Cleanup documentation
* Clarify merge process and Marge bot

HACKING.md  16 +
libraries/base/GHC/List.hs  433 ++++++++++++++++++++++++++++++
2 files changed, 367 insertions(+), 82 deletions()
diff git a/HACKING.md b/HACKING.md
index b1d41a7c5e..d7b74b6d8d 100644
 a/HACKING.md
+++ b/HACKING.md
@@ 12,7 +12,7 @@ The home for GHC hackers is our GitLab instance, located here:
From here, you can file bugs (or look them up,) use the wiki, view the
+From here, you can file bugs (or look them up), use the wiki, view the
`git` history, among other things. Of particular note is the building
page, which has the high level overview of the build process and how
to get the source:
@@ 34,7 +34,7 @@ $ git clone recursive git@gitlab.haskell.org:ghc/ghc.git
```
On Windows, you need an extra repository containing some build tools.
These can be downloaded for you by configure. This only needs to be done once by running:
+These can be downloaded for you by `configure`. This only needs to be done once by running:
```
$ ./configure enabletarballsautodownload
@@ 50,7 +50,7 @@ $ ... doublecheck mk/build.mk ...
```
Now build. The convenient `validate` script will build the tree in a way which
is both quick to build and consistent with our testsuite,
+is both quick to build and consistent with our testsuite:
```
$ ./validate buildonly
@@ 62,15 +62,15 @@ newly built compiler.
Now, hack on your copy and rebuild (with `make`) as necessary.
Then start by making your commits however you want. When you're done, you can submit
 a pull request on Github for small changes. For larger changes the patch needs to be
 submitted to [GitLab](https://gitlab.haskell.org/ghc/ghc/merge_requests) for code review.
 The GHC Wiki has a good summary for the [overall process](https://gitlab.haskell.org/ghc/ghc/wikis/workingconventions/fixingbugs).
+a pull request on Github for small changes. For larger changes the patch needs to be
+submitted to [GitLab](https://gitlab.haskell.org/ghc/ghc/merge_requests) for code review.
+The GHC Wiki has a good summary for the [overall process](https://gitlab.haskell.org/ghc/ghc/wikis/workingconventions/fixingbugs). One or several reviewers will review your PR, and when they are ok with your changes, they will assign the PR to [Marge Bot](https://gitlab.haskell.org/margebot) which will automatically rebase, batch and then merge your PR (assuming the build passes).
Useful links:
=============
An overview of things like using git, the release process, filing bugs
+An overview of things like using Git, the release process, filing bugs
and more can be located here:
@@ 94,8 +94,6 @@ and type information of the GHC sources is available at:
Look for `GHC` in `Packagename`. For example, here is the link to
[GHC8.6.5](https://haskellcodeexplorer.mfix.io/package/ghc8.6.5).


If you want to watch issues and code review activities, the following page is a good start:
diff git a/libraries/base/GHC/List.hs b/libraries/base/GHC/List.hs
index 10ba7d802d..3215f12b5b 100644
 a/libraries/base/GHC/List.hs
+++ b/libraries/base/GHC/List.hs
@@ 169,7 +169,7 @@ null (_:_) = False
 0
 >>> length ['a', 'b', 'c']
 3
 length [1..]
+ >>> length [1..]
 * Hangs forever *
{# NOINLINE [1] length #}
length :: [a] > Int
@@ 245,6 +245,8 @@ filterFB c p x r  p x = x `c` r
 90
 >>> foldl (\reversedString nextChar > nextChar : reversedString) "foo" ['a', 'b', 'c', 'd']
 "dcbafoo"
+ >>> foldl (+) 0 [1..]
+ * Hangs forever *
foldl :: forall a b. (b > a > b) > b > [a] > b
{# INLINE foldl #}
foldl k z0 xs =
@@ 298,12 +300,25 @@ foldl' k z0 xs =
 See Note [Left folds via right fold]
  'foldl1' is a variant of 'foldl' that has no starting value argument,
 and thus must be applied to nonempty lists.
+ and thus must be applied to nonempty lists. Note that unlike 'foldl', the accumulated value must be of the same type as the list elements.
+
+ >>> foldl1 (+) [1..4]
+ 10
+ >>> foldl1 (+) []
+ Exception: Prelude.foldl1: empty list
+ >>> foldl1 () [1..4]
+ 8
+ >>> foldl1 (&&) [True, False, True, True]
+ False
+ >>> foldl1 () [False, False, True, True]
+ True
+ >>> foldl1 (+) [1..]
+ * Hangs forever *
foldl1 :: (a > a > a) > [a] > a
foldl1 f (x:xs) = foldl f x xs
foldl1 _ [] = errorEmptyList "foldl1"
  A strict version of 'foldl1'
+  A strict version of 'foldl1'.
foldl1' :: (a > a > a) > [a] > a
foldl1' f (x:xs) = foldl' f x xs
foldl1' _ [] = errorEmptyList "foldl1'"
@@ 312,11 +327,33 @@ foldl1' _ [] = errorEmptyList "foldl1'"
 List sum and product
  The 'sum' function computes the sum of a finite list of numbers.
+
+ >>> sum []
+ 0
+ >>> sum [42]
+ 42
+ >>> sum [1..10]
+ 55
+ >>> sum [4.1, 2.0, 1.7]
+ 7.8
+ >>> sum [1..]
+ * Hangs forever *
sum :: (Num a) => [a] > a
{# INLINE sum #}
sum = foldl (+) 0
  The 'product' function computes the product of a finite list of numbers.
+
+ >>> product []
+ 1
+ >>> product [42]
+ 42
+ >>> product [1..10]
+ 3628800
+ >>> product [4.1, 2.0, 1.7]
+ 13.939999999999998
+ >>> product [1..]
+ * Hangs forever *
product :: (Num a) => [a] > a
{# INLINE product #}
product = foldl (*) 1
@@ 328,7 +365,18 @@ product = foldl (*) 1

 Note that

 > last (scanl f z xs) == foldl f z xs.
+ > last (scanl f z xs) == foldl f z xs
+
+ >>> scanl (+) 0 [1..4]
+ [0,1,3,6,10]
+ >>> scanl (+) 42 []
+ [42]
+ >>> scanl () 100 [1..4]
+ [100,99,97,94,90]
+ >>> scanl (\reversedString nextChar > nextChar : reversedString) "foo" ['a', 'b', 'c', 'd']
+ ["foo","afoo","bafoo","cbafoo","dcbafoo"]
+ >>> scanl (+) 0 [1..]
+ * Hangs forever *
 This peculiar arrangement is necessary to prevent scanl being rewritten in
 its own righthand side.
@@ 363,12 +411,24 @@ constScanl = const
 value argument:

 > scanl1 f [x1, x2, ...] == [x1, x1 `f` x2, ...]

+
+ >>> scanl1 (+) [1..4]
+ [1,3,6,10]
+ >>> scanl1 (+) []
+ []
+ >>> scanl1 () [1..4]
+ [1,1,4,8]
+ >>> scanl1 (&&) [True, False, True, True]
+ [True,False,False,False]
+ >>> scanl1 () [False, False, True, True]
+ [False,False,True,True]
+ >>> scanl1 (+) [1..]
+ * Hangs forever *
scanl1 :: (a > a > a) > [a] > [a]
scanl1 f (x:xs) = scanl f x xs
scanl1 _ [] = []
  \(\mathcal{O}(n)\). A strictly accumulating version of 'scanl'
+  \(\mathcal{O}(n)\). A strict version of 'scanl'.
{# NOINLINE [1] scanl' #}
scanl' :: (b > a > b) > b > [a] > [b]
 This peculiar form is needed to prevent scanl' from being rewritten
@@ 431,8 +491,20 @@ match on everything past the :, which is just the tail of scanl.
 above functions.
  'foldr1' is a variant of 'foldr' that has no starting value argument,
 and thus must be applied to nonempty lists.

+ and thus must be applied to nonempty lists. Note that unlike 'foldr', the accumulated value must be of the same type as the list elements.
+
+ >>> foldr1 (+) [1..4]
+ 10
+ >>> foldr1 (+) []
+ Exception: Prelude.foldr1: empty list
+ >>> foldr1 () [1..4]
+ 2
+ >>> foldr1 (&&) [True, False, True, True]
+ False
+ >>> foldr1 () [False, False, True, True]
+ True
+ >>> foldr1 (+) [1..]
+ * Hangs forever *
foldr1 :: (a > a > a) > [a] > a
foldr1 f = go
where go [x] = x
@@ 440,10 +512,21 @@ foldr1 f = go
go [] = errorEmptyList "foldr1"
{# INLINE [0] foldr1 #}
  \(\mathcal{O}(n)\). 'scanr' is the righttoleft dual of 'scanl'.
 Note that
+  \(\mathcal{O}(n)\). 'scanr' is the righttoleft dual of 'scanl'. Note that the order of parameters on the accumulating function are reversed compared to 'scanl'.
+ Also note that

 > head (scanr f z xs) == foldr f z xs.
+
+ >>> scanr (+) 0 [1..4]
+ [10,9,7,4,0]
+ >>> scanr (+) 42 []
+ [42]
+ >>> scanr () 100 [1..4]
+ [98,97,99,96,100]
+ >>> scanr (\nextChar reversedString > nextChar : reversedString) "foo" ['a', 'b', 'c', 'd']
+ ["abcdfoo","bcdfoo","cdfoo","dfoo","foo"]
+ >>> scanr (+) 0 [1..]
+ * Hangs forever *
{# NOINLINE [1] scanr #}
scanr :: (a > b > b) > b > [a] > [b]
scanr _ q0 [] = [q0]
@@ 496,6 +579,19 @@ remove the cause for the chain of evaluations, and all is well.
  \(\mathcal{O}(n)\). 'scanr1' is a variant of 'scanr' that has no starting
 value argument.
+
+ >>> scanr1 (+) [1..4]
+ [10,9,7,4]
+ >>> scanr1 (+) []
+ []
+ >>> scanr1 () [1..4]
+ [2,3,1,4]
+ >>> scanr1 (&&) [True, False, True, True]
+ [False,False,True,True]
+ >>> scanr1 () [True, True, False, False]
+ [True,True,False,False]
+ >>> scanr1 (+) [1..]
+ * Hangs forever *
scanr1 :: (a > a > a) > [a] > [a]
scanr1 _ [] = []
scanr1 _ [x] = [x]
@@ 506,6 +602,15 @@ scanr1 f (x:xs) = f x q : qs
 which must be nonempty, finite, and of an ordered type.
 It is a special case of 'Data.List.maximumBy', which allows the
 programmer to supply their own comparison function.
+
+ >>> maximum []
+ Exception: Prelude.maximum: empty list
+ >>> maximum [42]
+ 42
+ >>> maximum [55, 12, 7, 0, 89]
+ 55
+ >>> maximum [1..]
+ * Hangs forever *
maximum :: (Ord a) => [a] > a
{# INLINABLE maximum #}
maximum [] = errorEmptyList "maximum"
@@ 521,6 +626,15 @@ maximum xs = foldl1 max xs
 which must be nonempty, finite, and of an ordered type.
 It is a special case of 'Data.List.minimumBy', which allows the
 programmer to supply their own comparison function.
+
+ >>> minimum []
+ Exception: Prelude.minimum: empty list
+ >>> minimum [42]
+ 42
+ >>> minimum [55, 12, 7, 0, 89]
+ 89
+ >>> minimum [1..]
+ * Hangs forever *
minimum :: (Ord a) => [a] > a
{# INLINABLE minimum #}
minimum [] = errorEmptyList "minimum"
@@ 538,6 +652,11 @@ minimum xs = foldl1 min xs
 Note that 'iterate' is lazy, potentially leading to thunk buildup if
 the consumer doesn't force each iterate. See 'iterate'' for a strict
 variant of this function.
+
+ >>> iterate not True
+ [True,False,True,False...
+ >>> iterate (+3) 42
+ [42,45,48,51,54,57,60,63...
{# NOINLINE [1] iterate #}
iterate :: (a > a) > a > [a]
iterate f x = x : iterate f (f x)
@@ 555,8 +674,9 @@ iterateFB c f x0 = go x0
  'iterate'' is the strict version of 'iterate'.

 It ensures that the result of each application of force to weak head normal
 form before proceeding.
+ It forces the result of each application of the function to weak head normal
+ form (WHNF)
+ before proceeding.
{# NOINLINE [1] iterate' #}
iterate' :: (a > a) > a > [a]
iterate' f x =
@@ 577,6 +697,9 @@ iterate'FB c f x0 = go x0
  'repeat' @x@ is an infinite list, with @x@ the value of every element.
+
+ >>> repeat 17
+[17,17,17,17,17,17,17,17,17...
repeat :: a > [a]
{# INLINE [0] repeat #}
 The pragma just gives the rules more chance to fire
@@ 596,6 +719,13 @@ repeatFB c x = xs where xs = x `c` xs
 every element.
 It is an instance of the more general 'Data.List.genericReplicate',
 in which @n@ may be of any integral type.
+
+ >>> replicate 0 True
+ []
+ >>> replicate (1) True
+ []
+ >>> replicate 4 True
+ [True,True,True,True]
{# INLINE replicate #}
replicate :: Int > a > [a]
replicate n x = take n (repeat x)
@@ 603,19 +733,26 @@ replicate n x = take n (repeat x)
  'cycle' ties a finite list into a circular one, or equivalently,
 the infinite repetition of the original list. It is the identity
 on infinite lists.

+
+ >>> cycle []
+ Exception: Prelude.cycle: empty list
+ >>> cycle [42]
+ [42,42,42,42,42,42,42,42,42,42...
+ >>> cycle [2, 5, 7]
+ [2,5,7,2,5,7,2,5,7,2,5,7...
cycle :: [a] > [a]
cycle [] = errorEmptyList "cycle"
cycle xs = xs' where xs' = xs ++ xs'
  'takeWhile', applied to a predicate @p@ and a list @xs@, returns the
 longest prefix (possibly empty) of @xs@ of elements that satisfy @p@:

 > takeWhile (< 3) [1,2,3,4,1,2,3,4] == [1,2]
 > takeWhile (< 9) [1,2,3] == [1,2,3]
 > takeWhile (< 0) [1,2,3] == []
+ longest prefix (possibly empty) of @xs@ of elements that satisfy @p@.


+ >>> takeWhile (< 3) [1,2,3,4,1,2,3,4]
+ [1,2]
+ >>> takeWhile (< 9) [1,2,3]
+ [1,2,3]
+ >>> takeWhile (< 0) [1,2,3]
+ []
{# NOINLINE [1] takeWhile #}
takeWhile :: (a > Bool) > [a] > [a]
takeWhile _ [] = []
@@ 642,13 +779,14 @@ takeWhileFB p c n = \x r > if p x then x `c` r else n
takeWhileFB (\x > q x && p x) c n
#}
  'dropWhile' @p xs@ returns the suffix remaining after 'takeWhile' @p xs@:

 > dropWhile (< 3) [1,2,3,4,5,1,2,3] == [3,4,5,1,2,3]
 > dropWhile (< 9) [1,2,3] == []
 > dropWhile (< 0) [1,2,3] == [1,2,3]
+  'dropWhile' @p xs@ returns the suffix remaining after 'takeWhile' @p xs@.


+ >>> dropWhile (< 3) [1,2,3,4,5,1,2,3]
+ [3,4,5,1,2,3]
+ >>> dropWhile (< 9) [1,2,3]
+ []
+ >>> dropWhile (< 0) [1,2,3]
+ [1,2,3]
dropWhile :: (a > Bool) > [a] > [a]
dropWhile _ [] = []
dropWhile p xs@(x:xs')
@@ 656,14 +794,20 @@ dropWhile p xs@(x:xs')
 otherwise = xs
  'take' @n@, applied to a list @xs@, returns the prefix of @xs@
 of length @n@, or @xs@ itself if @n > 'length' xs@:
+ of length @n@, or @xs@ itself if @n > 'length' xs@.

 > take 5 "Hello World!" == "Hello"
 > take 3 [1,2,3,4,5] == [1,2,3]
 > take 3 [1,2] == [1,2]
 > take 3 [] == []
 > take (1) [1,2] == []
 > take 0 [1,2] == []
+ >>> take 5 "Hello World!"
+ "Hello"
+ >>> take 3 [1,2,3,4,5]
+ [1,2,3]
+ >>> take 3 [1,2]
+ [1,2]
+ >>> take 3 []
+ []
+ >>> take (1) [1,2]
+ []
+ >>> take 0 [1,2]
+ []

 It is an instance of the more general 'Data.List.genericTake',
 in which @n@ may be of any integral type.
@@ 723,14 +867,20 @@ takeFB c n x xs
#endif
  'drop' @n xs@ returns the suffix of @xs@
 after the first @n@ elements, or @[]@ if @n > 'length' xs@:
+ after the first @n@ elements, or @[]@ if @n > 'length' xs@.

 > drop 6 "Hello World!" == "World!"
 > drop 3 [1,2,3,4,5] == [4,5]
 > drop 3 [1,2] == []
 > drop 3 [] == []
 > drop (1) [1,2] == [1,2]
 > drop 0 [1,2] == [1,2]
+ >>> drop 6 "Hello World!"
+ "World!"
+ >>> drop 3 [1,2,3,4,5]
+ [4,5]
+ >>> drop 3 [1,2]
+ []
+ >>> drop 3 []
+ []
+ >>> drop (1) [1,2]
+ [1,2]
+ >>> drop 0 [1,2]
+ [1,2]

 It is an instance of the more general 'Data.List.genericDrop',
 in which @n@ may be of any integral type.
@@ 756,13 +906,20 @@ drop n ls
  'splitAt' @n xs@ returns a tuple where first element is @xs@ prefix of
 length @n@ and second element is the remainder of the list:

 > splitAt 6 "Hello World!" == ("Hello ","World!")
 > splitAt 3 [1,2,3,4,5] == ([1,2,3],[4,5])
 > splitAt 1 [1,2,3] == ([1],[2,3])
 > splitAt 3 [1,2,3] == ([1,2,3],[])
 > splitAt 4 [1,2,3] == ([1,2,3],[])
 > splitAt 0 [1,2,3] == ([],[1,2,3])
 > splitAt (1) [1,2,3] == ([],[1,2,3])
+ >>> splitAt 6 "Hello World!"
+ ("Hello ","World!")
+ >>> splitAt 3 [1,2,3,4,5]
+ ([1,2,3],[4,5])
+ >>> splitAt 1 [1,2,3]
+ ([1],[2,3])
+ >>> splitAt 3 [1,2,3]
+ ([1,2,3],[])
+ >>> splitAt 4 [1,2,3]
+ ([1,2,3],[])
+ >>> splitAt 0 [1,2,3]
+ ([],[1,2,3])
+ >>> splitAt (1) [1,2,3]
+ ([],[1,2,3])

 It is equivalent to @('take' n xs, 'drop' n xs)@ when @n@ is not @__@
 (@splitAt __ xs = __@).
@@ 789,12 +946,14 @@ splitAt n ls
 first element is longest prefix (possibly empty) of @xs@ of elements that
 satisfy @p@ and second element is the remainder of the list:

 > span (< 3) [1,2,3,4,1,2,3,4] == ([1,2],[3,4,1,2,3,4])
 > span (< 9) [1,2,3] == ([1,2,3],[])
 > span (< 0) [1,2,3] == ([],[1,2,3])
+ >>> span (< 3) [1,2,3,4,1,2,3,4]
+ ([1,2],[3,4,1,2,3,4])
+ >>> span (< 9) [1,2,3]
+ ([1,2,3],[])
+ >>> span (< 0) [1,2,3]
+ ([],[1,2,3])

 'span' @p xs@ is equivalent to @('takeWhile' p xs, 'dropWhile' p xs)@

span :: (a > Bool) > [a] > ([a],[a])
span _ xs@[] = (xs, xs)
span p xs@(x:xs')
@@ 805,12 +964,14 @@ span p xs@(x:xs')
 first element is longest prefix (possibly empty) of @xs@ of elements that
 /do not satisfy/ @p@ and second element is the remainder of the list:

 > break (> 3) [1,2,3,4,1,2,3,4] == ([1,2,3],[4,1,2,3,4])
 > break (< 9) [1,2,3] == ([],[1,2,3])
 > break (> 9) [1,2,3] == ([1,2,3],[])
+ >>> break (> 3) [1,2,3,4,1,2,3,4]
+ ([1,2,3],[4,1,2,3,4])
+ >>> break (< 9) [1,2,3]
+ ([],[1,2,3])
+ >>> break (> 9) [1,2,3]
+ ([1,2,3],[])

 'break' @p@ is equivalent to @'span' ('not' . p)@.

break :: (a > Bool) > [a] > ([a],[a])
#if defined(USE_REPORT_PRELUDE)
break p = span (not . p)
@@ 824,6 +985,15 @@ break p xs@(x:xs')
  'reverse' @xs@ returns the elements of @xs@ in reverse order.
 @xs@ must be finite.
+
+ >>> reverse []
+ []
+ >>> reverse [42]
+ [42]
+ >>> reverse [2,5,7]
+ [7,5,2]
+ >>> reverse [1..]
+ * Hangs forever *
reverse :: [a] > [a]
#if defined(USE_REPORT_PRELUDE)
reverse = foldl (flip (:)) []
@@ 834,9 +1004,22 @@ reverse l = rev l []
rev (x:xs) a = rev xs (x:a)
#endif
  'and' returns the conjunction of a Boolean list. For the result to be
+  'and' returns the conjunction of a Boolean list. For the result to be
 'True', the list must be finite; 'False', however, results from a 'False'
 value at a finite index of a finite or infinite list.
+
+ >>> and []
+ True
+ >>> and [True]
+ True
+ >>> and [False]
+ False
+ >>> and [True, True, False]
+ False
+ >>> and (False : repeat True)  Infinite list [False,True,True,True,True,True,True...
+ False
+ >>> and (repeat True)
+ * Hangs forever *
and :: [Bool] > Bool
#if defined(USE_REPORT_PRELUDE)
and = foldr (&&) True
@@ 851,9 +1034,22 @@ and (x:xs) = x && and xs
#}
#endif
  'or' returns the disjunction of a Boolean list. For the result to be
+  'or' returns the disjunction of a Boolean list. For the result to be
 'False', the list must be finite; 'True', however, results from a 'True'
 value at a finite index of a finite or infinite list.
+
+ >>> or []
+ False
+ >>> or [True]
+ True
+ >>> or [False]
+ False
+ >>> or [True, True, False]
+ True
+ >>> or (True : repeat False)  Infinite list [True,False,False,False,False,False,False...
+ True
+ >>> or (repeat False)
+ * Hangs forever *
or :: [Bool] > Bool
#if defined(USE_REPORT_PRELUDE)
or = foldr () False
@@ 869,11 +1065,22 @@ or (x:xs) = x  or xs
#endif
  Applied to a predicate and a list, 'any' determines if any element
 of the list satisfies the predicate. For the result to be
+ of the list satisfies the predicate. For the result to be
 'False', the list must be finite; 'True', however, results from a 'True'
 value for the predicate applied to an element at a finite index of a finite or infinite list.
+ value for the predicate applied to an element at a finite index of a finite
+ or infinite list.
+
+ >>> any (> 3) []
+ False
+ >>> any (> 3) [1,2]
+ False
+ >>> any (> 3) [1,2,3,4,5]
+ True
+ >>> any (> 3) [1..]
+ True
+ >>> any (> 3) [0, 1..]
+ * Hangs forever *
any :: (a > Bool) > [a] > Bool

#if defined(USE_REPORT_PRELUDE)
any p = or . map p
#else
@@ 891,7 +1098,19 @@ any p (x:xs) = p x  any p xs
  Applied to a predicate and a list, 'all' determines if all elements
 of the list satisfy the predicate. For the result to be
 'True', the list must be finite; 'False', however, results from a 'False'
 value for the predicate applied to an element at a finite index of a finite or infinite list.
+ value for the predicate applied to an element at a finite index of a finite
+ or infinite list.
+
+ >>> all (> 3) []
+ True
+ >>> all (> 3) [1,2]
+ False
+ >>> all (> 3) [1,2,3,4,5]
+ False
+ >>> all (> 3) [1..]
+ False
+ >>> all (> 3) [4..]
+ * Hangs forever *
all :: (a > Bool) > [a] > Bool
#if defined(USE_REPORT_PRELUDE)
all p = and . map p
@@ 911,6 +1130,17 @@ all p (x:xs) = p x && all p xs
 e.g., @x \`elem\` xs@. For the result to be
 'False', the list must be finite; 'True', however, results from an element
 equal to @x@ found at a finite index of a finite or infinite list.
+
+ >>> 3 `elem` []
+ False
+ >>> 3 `elem` [1,2]
+ False
+ >>> 3 `elem` [1,2,3,4,5]
+ True
+ >>> 3 `elem` [1..]
+ True
+ >>> 3 `elem` [4..]
+ * Hangs forever *
elem :: (Eq a) => a > [a] > Bool
#if defined(USE_REPORT_PRELUDE)
elem x = any (== x)
@@ 925,6 +1155,17 @@ elem x (y:ys) = x==y  elem x ys
#endif
  'notElem' is the negation of 'elem'.
+
+ >>> 3 `notElem` []
+ True
+ >>> 3 `notElem` [1,2]
+ True
+ >>> 3 `notElem` [1,2,3,4,5]
+ False
+ >>> 3 `notElem` [1..]
+ False
+ >>> 3 `notElem` [4..]
+ * Hangs forever *
notElem :: (Eq a) => a > [a] > Bool
#if defined(USE_REPORT_PRELUDE)
notElem x = all (/= x)
@@ 941,6 +1182,10 @@ notElem x (y:ys)= x /= y && notElem x ys
  \(\mathcal{O}(n)\). 'lookup' @key assocs@ looks up a key in an association
 list.

+ >>> lookup 2 []
+ Nothing
+ >>> lookup 2 [(1, "first")]
+ Nothing
 >>> lookup 2 [(1, "first"), (2, "second"), (3, "third")]
 Just "second"
lookup :: (Eq a) => a > [(a,b)] > Maybe b
@@ 949,7 +1194,15 @@ lookup key ((x,y):xys)
 key == x = Just y
 otherwise = lookup key xys
  Map a function over a list and concatenate the results.
+  Map a function returning a list over a list and concatenate the results.
+ 'concatMap' can be seen as the composition of 'concat' and 'map'.
+
+ > concatMap f xs == (concat . map f) xs
+
+ >>> concatMap (\i > [i,i]) []
+ []
+ >>> concatMap (\i > [i,i]) [1,2,3]
+ [1,1,2,2,3,3]
concatMap :: (a > [b]) > [a] > [b]
concatMap f = foldr ((++) . f) []
@@ 962,6 +1215,13 @@ concatMap f = foldr ((++) . f) []
  Concatenate a list of lists.
+
+ >>> concat []
+ []
+ >>> concat [[42]]
+ [42]
+ >>> concat [[1,2,3], [4,5], [6], []]
+ [1,2,3,4,5,6]
concat :: [[a]] > [a]
concat = foldr (++) []
@@ 1111,18 +1371,27 @@ NB: Zips for larger tuples are in the List module.
  \(\mathcal{O}(\min(m,n))\). 'zip' takes two lists and returns a list of
 corresponding pairs.

 > zip [1, 2] ['a', 'b'] = [(1, 'a'), (2, 'b')]
+ >>> zip [1, 2] ['a', 'b']
+ [(1, 'a'), (2, 'b')]

 If one input list is short, excess elements of the longer list are
 discarded:
+ If one input list is shorter than the other, excess elements of the longer
+ list are discarded, even if one of the lists is infinite:

 > zip [1] ['a', 'b'] = [(1, 'a')]
 > zip [1, 2] ['a'] = [(1, 'a')]
+ >>> zip [1] ['a', 'b']
+ [(1, 'a')]
+ >>> zip [1, 2] ['a']
+ [(1, 'a')]
+ >>> zip [] [1..]
+ []
+ >>> zip [1..] []
+ []

 'zip' is rightlazy:

 > zip [] __ = []
 > zip __ [] = __
+ >>> zip [] __
+ []
+ >>> zip __ []
+ __

 'zip' is capable of list fusion, but it is restricted to its
 first list argument and its resulting list.
@@ 1167,8 +1436,12 @@ zip3FB cons = \a b c r > (a,b,c) `cons` r

  \(\mathcal{O}(\min(m,n))\). 'zipWith' generalises 'zip' by zipping with the
 function given as the first argument, instead of a tupling function. For
 example, @'zipWith' (+)@ is applied to two lists to produce the list of
+ function given as the first argument, instead of a tupling function.
+
+ > zipWith (,) xs ys == zip xs ys
+ > zipWith f [x1,x2,x3..] [y1,y2,y3..] == [f x1 y1, f x2 y2, f x3 y3..]
+
+ For example, @'zipWith' (+)@ is applied to two lists to produce the list of
 corresponding sums:

 >>> zipWith (+) [1, 2, 3] [4, 5, 6]
@@ 1176,7 +1449,8 @@ zip3FB cons = \a b c r > (a,b,c) `cons` r

 'zipWith' is rightlazy:

 > zipWith f [] __ = []
+ >>> zipWith f [] __
+ []

 'zipWith' is capable of list fusion, but it is restricted to its
 first list argument and its resulting list.
@@ 1200,10 +1474,13 @@ zipWithFB c f = \x y r > (x `f` y) `c` r
#}
  The 'zipWith3' function takes a function which combines three
 elements, as well as three lists and returns a list of their pointwise
 combination, analogous to 'zipWith'.
+ elements, as well as three lists and returns a list of the function applied
+ to corresponding elements, analogous to 'zipWith'.
 It is capable of list fusion, but it is restricted to its
 first list argument and its resulting list.
+
+ > zipWith3 (,,) xs ys zs == zip3 xs ys zs
+ > zipWith3 f [x1,x2,x3..] [y1,y2,y3..] [z1,z2,z3..] == [f x1 y1 z1, f x2 y2 z2, f x3 y3 z3..]
{# NOINLINE [1] zipWith3 #}
zipWith3 :: (a>b>c>d) > [a]>[b]>[c]>[d]
zipWith3 z = go
@@ 1222,6 +1499,11 @@ zipWith3FB cons func = \a b c r > (func a b c) `cons` r
  'unzip' transforms a list of pairs into a list of first components
 and a list of second components.
+
+ >>> unzip []
+ ([],[])
+ >>> unzip [(1, 'a'), (2, 'b')]
+ ([1,2],"ab")
unzip :: [(a,b)] > ([a],[b])
{# INLINE unzip #}
 Inline so that fusion `foldr` has an opportunity to fire.
@@ 1230,6 +1512,11 @@ unzip = foldr (\(a,b) ~(as,bs) > (a:as,b:bs)) ([],[])
  The 'unzip3' function takes a list of triples and returns three
 lists, analogous to 'unzip'.
+
+ >>> unzip3 []
+ ([],[],[])
+ >>> unzip3 [(1, 'a', True), (2, 'b', False)]
+ ([1,2],"ab",[True,False])
unzip3 :: [(a,b,c)] > ([a],[b],[c])
{# INLINE unzip3 #}
 Inline so that fusion `foldr` has an opportunity to fire.

2.25.4