HORIZON HASKELLDocslts/ghc-9.10.x248f8f02026-10-05Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05

Improved standard functions

8 declarations
valueinits :: [a] -> [[a]]
#

This function is lazier than the one suggested in the Haskell 98 report. It is inits undefined = [] : undefined, in contrast to Data.List.inits undefined = undefined.

valuetails :: [a] -> [[a]]
#

This function is lazier than the one suggested in the Haskell 98 report. It is tails undefined = ([] : undefined) : undefined, in contrast to Data.List.tails undefined = undefined.

valuegroupBy :: (a -> a -> Bool) -> [a] -> [[a]]
#

This function compares adjacent elements of a list. If two adjacent elements satisfy a relation then they are put into the same sublist. Example:

Example1 expression
groupBy (<) "abcdebcdef"["abcde","bcdef"]

In contrast to that groupBy compares the head of each sublist with each candidate for this sublist. This yields

Example1 expression
List.groupBy (<) "abcdebcdef"["abcdebcdef"]

The second b is compared with the leading a. Thus it is put into the same sublist as a.

The sublists are never empty. Thus the more precise result type would be [(a,[a])].

valuegroup :: Eq a => [a] -> [[a]]
#
valueunzip :: [(a, b)] -> ([a], [b])
#

Like standard unzip but more lazy. It is Data.List.unzip undefined == undefined, but unzip undefined == (undefined, undefined).

valuepartition :: (a -> Bool) -> [a] -> ([a], [a])
#

partition of GHC 6.2.1 fails on infinite lists. But this one does not.

valuespan :: (a -> Bool) -> [a] -> ([a], [a])
#

It is Data.List.span f undefined = undefined, whereas span f undefined = (undefined, undefined).

valuebreak :: (a -> Bool) -> [a] -> ([a], [a])
#

It is Data.List.span f undefined = undefined, whereas span f undefined = (undefined, undefined).

Split

18 declarations
valuechop :: (a -> Bool) -> [a] -> [[a]]
#

Split the list at the occurrences of a separator into sub-lists. Remove the separators. This is somehow a generalization of lines and words. But note the differences:

Example2 expressions
words "a  a"["a","a"]chop (' '==) "a  a"["a","","a"]
Example2 expressions
lines "a\n\na"["a","","a"]chop ('\n'==) "a\n\na"["a","","a"]
Example2 expressions
lines "a\n"["a"]chop ('\n'==) "a\n"["a",""]
valuebreakAfter :: (a -> Bool) -> [a] -> ([a], [a])
#

Like break, but splits after the matching element.

Property
forAllPredicates $ \p xs -> uncurry (++) (breakAfter p xs) == xs
valuetakeUntil :: (a -> Bool) -> [a] -> [a]
#

Take all elements until one matches. The matching element is returned, too. This is the key difference to takeWhile (not . p). It holds:

Property
forAllPredicates $ \p xs -> takeUntil p xs == fst (breakAfter p xs)
valuesegmentAfter :: (a -> Bool) -> [a] -> [[a]]
#

Split the list after each occurence of a terminator. Keep the terminator. There is always a list for the part after the last terminator. It may be empty. See package non-empty for more precise result type.

Property
forAllPredicates $ \p xs -> concat (segmentAfter p xs) == xs
Property
forAllPredicates $ \p xs -> length (filter p xs) == length (tail (segmentAfter p xs))
Property
forAllPredicates $ \p -> all (p . last) . init . segmentAfter p
Property
forAllPredicates $ \p -> all (all (not . p) . init) . init . segmentAfter p

This test captures both infinitely many groups and infinitely big groups:

Property
forAllPredicates $ \p x -> flip seq True . (!!100) . concat . segmentAfter p . cycle . (x:)
valuesegmentBefore :: (a -> Bool) -> [a] -> [[a]]
#

Split the list before each occurence of a leading character. Keep these characters. There is always a list for the part before the first leading character. It may be empty. See package non-empty for more precise result type.

Example2 expressions
segmentBefore isUpper "AbcdXyz"["","Abcd","Xyz"]segmentBefore isUpper "kAbcdXYZ"["k","Abcd","X","Y","Z"]
Property
forAllPredicates $ \p xs -> concat (segmentBefore p xs) == xs
Property
forAllPredicates $ \p xs -> length (filter p xs) == length (tail (segmentBefore p xs))
Property
forAllPredicates $ \p -> all (p . head) . tail . segmentBefore p
Property
forAllPredicates $ \p -> all (all (not . p) . tail) . tail . segmentBefore p
Property
forAllPredicates $ \p x -> flip seq True . (!!100) . concat . segmentBefore p . cycle . (x:)
valuesegmentAfterJust :: (a -> Maybe b) -> [a] -> ([([a], b)], [a])
#
Example1 expression
segmentAfterJust (\c -> toMaybe (isLetter c) (toUpper c)) "123a5345b---"([("123",'A'),("5345",'B')],"---")
valuesegmentBeforeJust :: (a -> Maybe b) -> [a] -> ([a], [(b, [a])])
#
Example1 expression
segmentBeforeJust (\c -> toMaybe (isLetter c) (toUpper c)) "123a5345b---"("123",[('A',"5345"),('B',"---")])
valuesegmentAfterRight :: [Either a b] -> ([([a], b)], [a])
#
Example1 expression
segmentAfterRight [Left 'a', Right LT, Right GT, Left 'b']([("a",LT),("",GT)],"b")
Property
forAllMaybeFn $ \f xs -> segmentAfterJust f xs == segmentAfterRight (map (\x -> maybe (Left x) Right (f x)) xs)
valuesegmentBeforeRight :: [Either a b] -> ([a], [(b, [a])])
#
Example1 expression
segmentBeforeRight [Left 'a', Right LT, Right GT, Left 'b']("a",[(LT,""),(GT,"b")])
Property
forAllMaybeFn $ \f xs -> segmentBeforeJust f xs == segmentBeforeRight (map (\x -> maybe (Left x) Right (f x)) xs)
valueremoveEach :: [a] -> [(a, [a])]
#

removeEach xs represents a list of sublists of xs, where each element of xs is removed and the removed element is separated. It seems to be much simpler to achieve with zip xs (map (flip List.delete xs) xs), but the implementation of removeEach does not need the Eq instance and thus can also be used for lists of functions.

See also the proposal http://www.haskell.org/pipermail/libraries/2008-February/009270.html

Example3 expressions
removeEach "abc"[('a',"bc"),('b',"ac"),('c',"ab")]removeEach "a"[('a',"")]removeEach ""[]
valuesplitEverywhere :: [a] -> [([a], a, [a])]
#
Example3 expressions
splitEverywhere "abc"[("",'a',"bc"),("a",'b',"c"),("ab",'c',"")]splitEverywhere "a"[("",'a',"")]splitEverywhere ""[]
valuesplitLast :: [a] -> ([a], a)
#

Deprecated. use viewR instead

It holds splitLast xs == (init xs, last xs), but splitLast is more efficient if the last element is accessed after the initial ones, because it avoids memoizing list.

Property
\(NonEmpty xs) -> splitLast (xs::String)  ==  (init xs, last xs)
valueviewR :: [a] -> Maybe ([a], a)
#

Should be prefered to init and last.

Property
\xs -> maybe True ((init xs, last xs) == ) (viewR (xs::String))
valueswitchL :: b -> (a -> [a] -> b) -> [a] -> b
#

Should be prefered to head and tail.

valueswitchR :: b -> ([a] -> a -> b) -> [a] -> b
#

Should be prefered to init and last.

Property
\xs -> switchR True (\ixs lxs -> ixs == init xs && lxs == last xs) (xs::String)

List processing starting at the end

5 declarations
valuedropRev :: Int -> [a] -> [a]
#

dropRev n is like reverse . drop n . reverse but it is lazy enough to work for infinite lists, too.

Property
\n xs -> dropRev n (xs::String) == reverse (drop n (reverse xs))
valuetakeRev :: Int -> [a] -> [a]
#

takeRev n is like reverse . take n . reverse but it is lazy enough to work for infinite lists, too.

Property
\n xs -> takeRev n (xs::String) == reverse (take n (reverse xs))
valuesplitAtRev :: Int -> [a] -> ([a], [a])
#

splitAtRev n xs == (dropRev n xs, takeRev n xs).

Property
\n xs -> splitAtRev n (xs::String) == (dropRev n xs, takeRev n xs)
Property
\n xs -> (xs::String) == uncurry (++) (splitAtRev n xs)
valuedropWhileRev :: (a -> Bool) -> [a] -> [a]
#

Deprecated. Use dropWhile from Data.List.Reverse.StrictElement or Data.List.Reverse.StrictSpine instead

valuetakeWhileRev :: (a -> Bool) -> [a] -> [a]
#

Deprecated. Use takeWhile from Data.List.Reverse.StrictElement or Data.List.Reverse.StrictSpine instead

List processing with Maybe and Either

8 declarations
valuemaybePrefixOf :: Eq a => [a] -> [a] -> Maybe [a]
#

maybePrefixOf xs ys is Just zs if xs is a prefix of ys, where zs is ys without the prefix xs. Otherwise it is Nothing. It is the same as stripPrefix.

Example2 expressions
maybePrefixOf "abc" "abcdef"Just "def"maybePrefixOf "def" "abcdef"Nothing
valuemaybeSuffixOf :: Eq a => [a] -> [a] -> Maybe [a]
#
Example2 expressions
maybeSuffixOf "abc" "abcdef"NothingmaybeSuffixOf "def" "abcdef"Just "abc"
valuepartitionMaybe :: (a -> Maybe b) -> [a] -> ([b], [a])
#

Partition a list into elements which evaluate to Just or Nothing by f.

Property
forAllMaybeFn $ \f xs -> partitionMaybe f xs == (mapMaybe f xs, filter (isNothing . f) xs)
Property
forAllPredicates $ \p xs -> partition p xs == partitionMaybe (\x -> toMaybe (p x) x) xs
valuetakeWhileJust :: [Maybe a] -> [a]
#

This is the cousin of takeWhile analogously to catMaybes being the cousin of filter.

Example1 expression
takeWhileJust [Just 'a', Just 'b', Nothing, Just 'c']"ab"

Example: Keep the heads of sublists until an empty list occurs.

Example1 expression
takeWhileJust $ map (fmap fst . viewL) ["abc","def","","xyz"]"ad"

For consistency with takeWhile, partitionMaybe and dropWhileNothing it should have been:

takeWhileJust_ :: (a -> Maybe b) -> a -> [b]

However, both variants are interchangeable:

takeWhileJust_ f == takeWhileJust . map f
takeWhileJust == takeWhileJust_ id
valuebreakJust :: (a -> Maybe b) -> [a] -> ([a], Maybe (b, [a]))
#
Property
forAllMaybeFn $ \f xs -> snd (breakJust f xs) == dropWhileNothing f xs

Sieve and slice

3 declarations
valuesieve :: Int -> [a] -> [a]
#

keep every k-th value from the list

Example1 expression
sieve 6 ['a'..'z']"agmsy"
valuesliceHorizontal :: Int -> [a] -> [[a]]
#
Example1 expression
sliceHorizontal 6 ['a'..'z']["agmsy","bhntz","ciou","djpv","ekqw","flrx"]
Property
\(NonEmpty xs) -> QC.forAll (QC.choose (1, length xs)) $ \n -> sliceHorizontal n xs == transpose (sliceVertical n (xs::String))
Property
\(NonEmpty xs) -> QC.forAll (QC.choose (1, length xs)) $ \n -> sliceVertical  n xs == transpose (sliceHorizontal n (xs::String))

The properties do not hold for empty lists because of:

Example1 expression
sliceHorizontal 4 ([]::[Int])[[],[],[],[]]
valuesliceVertical :: Int -> [a] -> [[a]]
#
Example1 expression
sliceVertical 6 ['a'..'z']["abcdef","ghijkl","mnopqr","stuvwx","yz"]

Search&replace

3 declarations
valuereplace :: Eq a => [a] -> [a] -> [a] -> [a]
#
Property
\(NonEmpty xs) ys -> replace xs xs ys == (ys::String)
Property
\(NonEmpty xs) (NonEmpty ys) -> equating (take 1000) (replace xs ys (cycle xs)) (cycle (ys::String))
valuemultiReplace :: Eq a => [([a], [a])] -> [a] -> [a]
#

prop src dst xs -> replace src dst xs == multiReplace (src,dst)

Lists of lists

3 declarations
valueshear :: [[a]] -> [[a]]
#

Transform

[[00,01,02,...],          [[00],
 [10,11,12,...],   -->     [10,01],
 [20,21,22,...],           [20,11,02],
 ...]                      ...]

With concat . shear you can perform a Cantor diagonalization, that is an enumeration of all elements of the sub-lists where each element is reachable within a finite number of steps. It is also useful for polynomial multiplication (convolution).

valueshearTranspose :: [[a]] -> [[a]]
#

Transform

[[00,01,02,...],          [[00],
 [10,11,12,...],   -->     [01,10],
 [20,21,22,...],           [02,11,20],
 ...]                      ...]

It's like shear but the order of elements in the sub list is reversed. Its implementation seems to be more efficient than that of shear. If the order does not matter, better choose shearTranspose.

Property
\xs -> shearTranspose xs  ==  map reverse (shear (xs::[String]))
valueouterProduct :: (a -> b -> c) -> [a] -> [b] -> [[c]]
#

Operate on each combination of elements of the first and the second list. In contrast to the list instance of Monad.liftM2 it holds the results in a list of lists.

Property
\xs ys -> let f x y = (x::Char,y::Int) in concat (outerProduct f xs ys)  ==  liftM2 f xs ys

Miscellaneous

16 declarations
valuetakeWhileMulti :: [a -> Bool] -> [a] -> [a]
#

Take while first predicate holds, then continue taking while second predicate holds, and so on.

valuerotate :: Int -> [a] -> [a]
#

rotate left

valuemergeBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]
#

Given two lists that are ordered (i.e. p x y holds for subsequent x and y) mergeBy them into a list that is ordered, again.

Example1 expression
mergeBy (<=) "agh" "begz""abegghz"
valueallEqual :: Eq a => [a] -> Bool
#
Example5 expressions
allEqual "aab"FalseallEqual "aaa"TrueallEqual "aa"TrueallEqual "a"TrueallEqual ""True
valueisAscending :: Ord a => [a] -> Bool
#
Example6 expressions
isAscending "abc"TrueisAscending "abb"TrueisAscending "aba"FalseisAscending "cba"FalseisAscending "a"TrueisAscending ""True
valuemapAdjacent :: (a -> a -> b) -> [a] -> [b]
#

This function combines every pair of neighbour elements in a list with a certain function.

Example4 expressions
mapAdjacent (<=) ""[]mapAdjacent (<=) "a"[]mapAdjacent (<=) "aba"[True,False]mapAdjacent (,) "abc"[('a','b'),('b','c')]
Property
\x xs -> mapAdjacent subtract (scanl (+) x xs) == (xs::[Integer])
valuemapAdjacent1 :: (a -> a -> b -> c) -> a -> [(a, b)] -> [c]
#
Example1 expression
let f x y z = [x,y]++show(z::Int) in mapAdjacent1 f 'a' [('b',1), ('c',2), ('d',3)]["ab1","bc2","cd3"]
valueequalWith :: (a -> b -> Bool) -> [a] -> [b] -> Bool
#
Example3 expressions
equalWith (<=) "ab" "bb"TrueequalWith (<=) "aa" "bbb"FalseequalWith (==) "aa" "aaa"False
Property
\as bs -> let f a b = abs (a-b) <= (10::Int) in equalWith f as bs ==  equalWithRec f as bs
Property
\as bs -> let f a b = abs (a-b) <= (10::Int) in equalWith f as bs ==  equalWithLiftM f as bs
valuerange :: Num a => Int -> [a]
#

Enumerate without Enum context. For Enum equivalent to enumFrom.

Example3 expressions
range 0 :: [Integer][]range 1 :: [Integer][0]range 8 :: [Integer][0,1,2,3,4,5,6,7]
Property
\(NonNegative n) -> length (range n :: [Integer]) == n
valueiterateAssociative :: (a -> a -> a) -> a -> [a]
#

For an associative operation op this computes iterateAssociative op a = iterate (op a) a but it is even faster than map (powerAssociative op a a) [0..] since it shares temporary results.

The idea is: From the list map (powerAssociative op a a) [0,(2*n)..] we compute the list map (powerAssociative op a a) [0,n..], and iterate that until n==1.

Property
\x -> equating (take 1000) (List.iterate (x+) x) (iterateAssociative (+) (x::Integer))
valueiterateLeaky :: (a -> a -> a) -> a -> [a]
#

This is equal to iterateAssociative. The idea is the following: The list we search is the fixpoint of the function: "Square all elements of the list, then spread it and fill the holes with successive numbers of their left neighbour." This also preserves log n applications per value. However it has a space leak, because for the value with index n all elements starting at div n 2 must be kept.

Property
\x -> equating (take 1000) (List.iterate (x+) x) (iterateLeaky (+) (x::Integer))
valuelengthAtLeast :: Int -> [a] -> Bool
#
Example5 expressions
lengthAtLeast 0 ""TruelengthAtLeast 3 "ab"FalselengthAtLeast 3 "abc"TruelengthAtLeast 3 $ repeat 'a'TruelengthAtLeast 3 $ "abc" ++ undefinedTrue
Property
\n xs -> lengthAtLeast n (xs::String)  ==  (length xs >= n)
valuelengthAtMost :: Int -> [a] -> Bool
#
Example6 expressions
lengthAtMost 0 ""TruelengthAtMost 3 "ab"TruelengthAtMost 3 "abc"TruelengthAtMost 3 "abcd"FalselengthAtMost 3 $ repeat 'a'FalselengthAtMost 3 $ "abcd" ++ undefinedFalse
Property
\n xs -> lengthAtMost n (xs::String)  ==  (length xs <= n)