HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Modulesplit-0.2.5Haskell2010

Data.List.Split.Internals

Implementation module for Data.List.Split, a combinator library for splitting lists. See the Data.List.Split documentation for more description and examples.

  • 7 types
  • 52 values
  • Packagesplit-0.2.5
  • Exports59
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceInternals.hs

Types and utilities

12 declarations
valuedefaultSplitter :: Splitter a
#

The default splitting strategy: keep delimiters in the output as separate chunks, don't condense multiple consecutive delimiters into one, keep initial and final blank chunks. Default delimiter is the constantly false predicate.

Note that defaultSplitter should normally not be used; use oneOf, onSublist, or whenElt instead, which are the same as the defaultSplitter with just the delimiter overridden.

The defaultSplitter strategy with any delimiter gives a maximally information-preserving splitting strategy, in the sense that (a) taking the concat of the output yields the original list, and (b) given only the output list, we can reconstruct a Splitter which would produce the same output list again given the original input list. This default strategy can be overridden to allow discarding various sorts of information.

newtypenewtype Delimiter a
#

A delimiter is a list of predicates on elements, matched by some contiguous subsequence of a list.

Constructors

valuematchDelim :: Delimiter a -> [a] -> Maybe ([a], [a])
#

Try to match a delimiter at the start of a list, either failing or decomposing the list into the portion which matched the delimiter and the remainder.

datadata DelimPolicy
#

What to do with delimiters?

Constructors

  • Drop

    Drop delimiters from the output.

  • Keep

    Keep delimiters as separate chunks of the output.

  • KeepLeft

    Keep delimiters in the output, prepending them to the following chunk.

  • KeepRight

    Keep delimiters in the output, appending them to the previous chunk.

Instances2Eq, Show
datadata CondensePolicy
#

What to do with multiple consecutive delimiters?

Constructors

  • Condense

    Condense into a single delimiter.

  • DropBlankFields

    Keep consecutive delimiters separate, but don't insert blank chunks in between them.

  • KeepBlankFields

    Insert blank chunks between consecutive delimiters.

Instances2Eq, Show
datadata EndPolicy
#

What to do with a blank chunk at either end of the list (i.e. when the list begins or ends with a delimiter).

Instances2Eq, Show
  • Eq EndPolicyDefined in split-0.2.5 · Data.List.Split.Internals
  • Show EndPolicyDefined in split-0.2.5 · Data.List.Split.Internals
datadata Chunk a
#

Tag chunks as delimiters or text.

Constructors

Instances2Eq, Show
  • Eq a => Eq (Chunk a)Defined in split-0.2.5 · Data.List.Split.Internals
  • Show a => Show (Chunk a)Defined in split-0.2.5 · Data.List.Split.Internals
typetype SplitList a = [Chunk a]
#

Internal representation of a split list that tracks which pieces are delimiters and which aren't.

Implementation

12 declarations
valuepostProcess :: Splitter a -> SplitList a -> SplitList a
#

Given a split list in the internal tagged representation, produce a new internal tagged representation corresponding to the final output, according to the strategy defined by the given Splitter.

valuemergeLeft :: SplitList a -> SplitList a
#

Merge delimiters with adjacent chunks to the right (yes, that's not a typo: the delimiters should end up on the left of the chunks, so they are merged with chunks to their right).

Combinators

1 declaration
valuesplit :: Splitter a -> [a] -> [[a]]
#

Split a list according to the given splitting strategy. This is how to "run" a Splitter that has been built using the other combinators.

Basic strategies

All these basic strategies have the same parameters as the defaultSplitter except for the delimiters.

valueoneOf :: Eq a => [a] -> Splitter a
#

A splitting strategy that splits on any one of the given elements.

Example1 expression
split (oneOf ",;") "hi;there,world"["hi",";","there",",","world"]
Example1 expression
split (oneOf "xyz") "aazbxyzcxd"["aa","z","b","x","","y","","z","c","x","d"]
valueonSublist :: Eq a => [a] -> Splitter a
#

A splitting strategy that splits on the given list, when it is encountered as an exact subsequence.

Example1 expression
split (onSublist "xyz") "aazbxyzcxd"["aazb","xyz","cxd"]

Note that splitting on the empty list is a special case, which splits just before every element of the list being split.

Example1 expression
split (onSublist "") "abc"["","","a","","b","","c"]
Example1 expression
split (dropDelims . dropBlanks $ onSublist "") "abc"["a","b","c"]

However, if you want to break a list into singleton elements like this, you are better off using chunksOf 1, or better yet, map (:[]).

valuewhenElt :: (a -> Bool) -> Splitter a
#

A splitting strategy that splits on any elements that satisfy the given predicate.

Example1 expression
split (whenElt (<0)) [2,4,-3,6,-9,1 :: Int][[2,4],[-3],[6],[-9],[1]]

Strategy transformers

valuedropDelims :: Splitter a -> Splitter a
#

Drop delimiters from the output (the default is to keep them).

Example1 expression
split (oneOf ":") "a:b:c"["a",":","b",":","c"]
Example1 expression
split (dropDelims $ oneOf ":") "a:b:c"["a","b","c"]
valuekeepDelimsL :: Splitter a -> Splitter a
#

Keep delimiters in the output by prepending them to adjacent chunks.

Example1 expression
split (keepDelimsL $ oneOf "xyz") "aazbxyzcxd"["aa","zb","x","y","zc","xd"]
valuekeepDelimsR :: Splitter a -> Splitter a
#

Keep delimiters in the output by appending them to adjacent chunks.

Example1 expression
split (keepDelimsR $ oneOf "xyz") "aazbxyzcxd"["aaz","bx","y","z","cx","d"]
valuecondense :: Splitter a -> Splitter a
#

Condense multiple consecutive delimiters into one.

Example1 expression
split (condense $ oneOf "xyz") "aazbxyzcxd"["aa","z","b","xyz","c","x","d"]
Example1 expression
split (dropDelims $ oneOf "xyz") "aazbxyzcxd"["aa","b","","","c","d"]
Example1 expression
split (condense . dropDelims $ oneOf "xyz") "aazbxyzcxd"["aa","b","c","d"]
valuedropInitBlank :: Splitter a -> Splitter a
#

Don't generate a blank chunk if there is a delimiter at the beginning.

Example1 expression
split (oneOf ":") ":a:b"["",":","a",":","b"]
Example1 expression
split (dropInitBlank $ oneOf ":") ":a:b"[":","a",":","b"]
valuedropFinalBlank :: Splitter a -> Splitter a
#

Don't generate a blank chunk if there is a delimiter at the end.

Example1 expression
split (oneOf ":") "a:b:"["a",":","b",":",""]
Example1 expression
split (dropFinalBlank $ oneOf ":") "a:b:"["a",":","b",":"]
valuedropInnerBlanks :: Splitter a -> Splitter a
#

Don't generate blank chunks between consecutive delimiters.

Example1 expression
split (oneOf ":") "::b:::a"["",":","",":","b",":","",":","",":","a"]
Example1 expression
split (dropInnerBlanks $ oneOf ":") "::b:::a"["",":",":","b",":",":",":","a"]
valuemapSplitter :: (b -> a) -> Splitter a -> Splitter b
#

Split over a different type of element by performing a preprocessing step.

Example1 expression
split (mapSplitter snd $ oneOf "-_") $ zip [0..] "a-bc_d"[[(0,'a')],[(1,'-')],[(2,'b'),(3,'c')],[(4,'_')],[(5,'d')]]
Example2 expressions
import Data.Char (toLower)split (mapSplitter toLower $ dropDelims $ whenElt (== 'x')) "abXcxd"["ab","c","d"]

Derived combinators

valuedropBlanks :: Splitter a -> Splitter a
#

Drop all blank chunks from the output, and condense consecutive delimiters into one. Equivalent to dropInitBlank . dropFinalBlank . condense.

Example1 expression
split (oneOf ":") "::b:::a"["",":","",":","b",":","",":","",":","a"]
Example1 expression
split (dropBlanks $ oneOf ":") "::b:::a"["::","b",":::","a"]
valuestartsWith :: Eq a => [a] -> Splitter a
#

Make a strategy that splits a list into chunks that all start with the given subsequence (except possibly the first). Equivalent to dropInitBlank . keepDelimsL . onSublist.

Example1 expression
split (startsWith "app") "applyapplicativeapplaudapproachapple"["apply","applicative","applaud","approach","apple"]
valuestartsWithOneOf :: Eq a => [a] -> Splitter a
#

Make a strategy that splits a list into chunks that all start with one of the given elements (except possibly the first). Equivalent to dropInitBlank . keepDelimsL . oneOf. example:

Example1 expression
split (startsWithOneOf ['A'..'Z']) "ACamelCaseIdentifier"["A","Camel","Case","Identifier"]
valueendsWith :: Eq a => [a] -> Splitter a
#

Make a strategy that splits a list into chunks that all end with the given subsequence, except possibly the last. Equivalent to dropFinalBlank . keepDelimsR . onSublist.

Example1 expression
split (endsWith "ly") "happilyslowlygnarlylily"["happily","slowly","gnarly","lily"]
valueendsWithOneOf :: Eq a => [a] -> Splitter a
#

Make a strategy that splits a list into chunks that all end with one of the given elements, except possibly the last. Equivalent to dropFinalBlank . keepDelimsR . oneOf.

Example1 expression
split (condense $ endsWithOneOf ".,?! ") "Hi, there!  How are you?"["Hi, ","there!  ","How ","are ","you?"]

Convenience functions

valuesplitOneOf :: Eq a => [a] -> [a] -> [[a]]
#

Split on any of the given elements. Equivalent to split . dropDelims . oneOf.

Example1 expression
splitOneOf ";.," "foo,bar;baz.glurk"["foo","bar","baz","glurk"]
valuesplitOn :: Eq a => [a] -> [a] -> [[a]]
#

Split on the given sublist. Equivalent to split . dropDelims . onSublist.

Example1 expression
splitOn ":" "12:35:07"["12","35","07"]
Example1 expression
splitOn "x" "axbxc"["a","b","c"]
Example1 expression
splitOn "x" "axbxcx"["a","b","c",""]
Example1 expression
splitOn ".." "a..b...c....d.."["a","b",".c","","d",""]

In some parsing combinator frameworks this is also known as sepBy.

Note that this is the right inverse of the intercalate function from Data.List, that is,

intercalate x . splitOn x === id

splitOn x . intercalate x is the identity on certain lists, but it is tricky to state the precise conditions under which this holds. (For example, it is not enough to say that x does not occur in any elements of the input list. Working out why is left as an exercise for the reader.)

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

Split on elements satisfying the given predicate. Equivalent to split . dropDelims . whenElt.

Example1 expression
splitWhen (<0) [1,3,-4,5,7,-9,0,2][[1,3],[5,7],[0,2]]
Example1 expression
splitWhen (<0) [1,-2,3,4,-5,-6,7,8,-9][[1],[3,4],[],[7,8],[]]
valuesepBy :: Eq a => [a] -> [a] -> [[a]]
#

Deprecated. Use splitOn.

valuesepByOneOf :: Eq a => [a] -> [a] -> [[a]]
#

Deprecated. Use splitOneOf.

valueendByOneOf :: Eq a => [a] -> [a] -> [[a]]
#

Split into chunks terminated by one of the given elements. Equivalent to split . dropFinalBlank . dropDelims . oneOf.

Example1 expression
endByOneOf ";," "foo;bar,baz;"["foo","bar","baz"]
valuewordsBy :: (a -> Bool) -> [a] -> [[a]]
#

Split into "words", with word boundaries indicated by the given predicate. Satisfies words === wordsBy isSpace; equivalent to split . dropBlanks . dropDelims . whenElt.

Example1 expression
wordsBy (`elem` ",;.?! ") "Hello there, world! How?"["Hello","there","world","How"]
Example1 expression
wordsBy (=='x') "dogxxxcatxbirdxx"["dog","cat","bird"]
valuelinesBy :: (a -> Bool) -> [a] -> [[a]]
#

Split into "lines", with line boundaries indicated by the given predicate. Satisfies lines === linesBy (=='n'); equivalent to split . dropFinalBlank . dropDelims . whenElt.

Example1 expression
linesBy (==';') "foo;bar;;baz;"["foo","bar","","baz"]
Example1 expression
linesBy (=='x') "dogxxxcatxbirdxx"["dog","","","cat","bird",""]

Other splitting methods

8 declarations
valuebuild :: ((a -> [a] -> [a]) -> [a] -> [a]) -> [a]
#

Standard build function, specialized to building lists.

Usually build is given the rank-2 type

build :: (forall b. (a -> b -> b) -> b -> b) -> [a]

but since we only use it when (b ~ [a]), we give it the more restricted type signature in order to avoid needing a non-Haskell2010 extension.

Note that the 0.1.4.3 release of this package did away with a custom build implementation in favor of importing one from GHC.Exts, which was (reportedly) faster for some applications. However, in the interest of simplicity and complete Haskell2010 compliance as split is being included in the Haskel Platform, version 0.2.1.0 has gone back to defining build manually. This is in line with split's design philosophy of having efficiency as a non-goal.

valuechunksOf :: Int -> [e] -> [[e]]
#

chunksOf n splits a list into length-n pieces. The last piece will be shorter if n does not evenly divide the length of the list. If n <= 0, chunksOf n l returns an infinite list of empty lists.

Example1 expression
chunksOf 3 [1..12][[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
Example1 expression
chunksOf 3 "Hello there"["Hel","lo ","the","re"]
Example1 expression
chunksOf 3 ([] :: [Int])[]

Note that chunksOf n [] is [], not [[]]. This is intentional, and satisfies the property that

chunksOf n xs ++ chunksOf n ys == chunksOf n (xs ++ ys)

whenever n evenly divides the length of xs.

valuechunk :: Int -> [e] -> [[e]]
#

Deprecated. Use chunksOf.

valuesplitPlaces :: Integral a => [a] -> [e] -> [[e]]
#

Split a list into chunks of the given lengths.

Example1 expression
splitPlaces [2,3,4] [1..20][[1,2],[3,4,5],[6,7,8,9]]
Example1 expression
splitPlaces [4,9] [1..10][[1,2,3,4],[5,6,7,8,9,10]]
Example1 expression
splitPlaces [4,9,3] [1..10][[1,2,3,4],[5,6,7,8,9,10]]

If the input list is longer than the total of the given lengths, then the remaining elements are dropped. If the list is shorter than the total of the given lengths, then the result may contain fewer chunks than requested, and the last chunk may be shorter than requested.

valuesplitPlacesBlanks :: Integral a => [a] -> [e] -> [[e]]
#

Split a list into chunks of the given lengths. Unlike splitPlaces, the output list will always be the same length as the first input argument. If the input list is longer than the total of the given lengths, then the remaining elements are dropped. If the list is shorter than the total of the given lengths, then the last several chunks will be shorter than requested or empty.

Example1 expression
splitPlacesBlanks [2,3,4] [1..20][[1,2],[3,4,5],[6,7,8,9]]
Example1 expression
splitPlacesBlanks [4,9] [1..10][[1,2,3,4],[5,6,7,8,9,10]]
Example1 expression
splitPlacesBlanks [4,9,3] [1..10][[1,2,3,4],[5,6,7,8,9,10],[]]

Notice the empty list in the output of the third example, which differs from the behavior of splitPlaces.

valuechop :: ([a] -> (b, [a])) -> [a] -> [b]
#

A useful recursion pattern for processing a list to produce a new list, often used for "chopping" up the input list. Typically chop is called with some function that will consume an initial prefix of the list and produce a value and the rest of the list.

For example, many common Prelude functions can be implemented in terms of chop:

group :: (Eq a) => [a] -> [[a]]
group = chop (\ xs@(x:_) -> span (==x) xs)

words :: String -> [String]
words = filter (not . null) . chop (break isSpace . dropWhile isSpace)
valuedivvy :: Int -> Int -> [a] -> [[a]]
#

Divides up an input list into a set of sublists, according to n and m input specifications you provide. Each sublist will have n items, and the start of each sublist will be offset by m items from the previous one.

Example1 expression
divvy 5 5 [1..15][[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]]
Example1 expression
divvy 5 2 [1..15][[1,2,3,4,5],[3,4,5,6,7],[5,6,7,8,9],[7,8,9,10,11],[9,10,11,12,13],[11,12,13,14,15]]

In the case where a source list's trailing elements do no fill an entire sublist, those trailing elements will be dropped.

Example1 expression
divvy 5 2 [1..10][[1,2,3,4,5],[3,4,5,6,7],[5,6,7,8,9]]

As an example, you can generate a moving average over a list of prices:

type Prices = [Float]
type AveragePrices = [Float]

average :: [Float] -> Float
average xs = sum xs / (fromIntegral $ length xs)

simpleMovingAverage :: Prices -> AveragePrices
simpleMovingAverage = map average . divvy 20 1