-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Combinator library for splitting lists. -- -- A collection of various methods for splitting lists into parts, akin -- to the "split" function found in several mainstream languages. Here is -- its tale: -- -- Once upon a time the standard Data.List module held no function -- for splitting a list into parts according to a delimiter. Many a brave -- lambda-knight strove to add such a function, but their striving was in -- vain, for Lo, the Supreme Council fell to bickering amongst themselves -- what was to be the essential nature of the One True Function which -- could cleave a list in twain (or thrain, or any required number of -- parts). -- -- And thus came to pass the split package, comprising divers functions -- for splitting a list asunder, each according to its nature. And the -- Supreme Council had no longer any grounds for argument, for the -- favored method of each was contained therein. -- -- To get started, see the Data.List.Split module. @package split @version 0.2.3.5 -- | Implementation module for Data.List.Split, a combinator library -- for splitting lists. See the Data.List.Split documentation for -- more description and examples. module Data.List.Split.Internals -- | A splitting strategy. data Splitter a Splitter :: Delimiter a -> DelimPolicy -> CondensePolicy -> EndPolicy -> EndPolicy -> Splitter a -- | What delimiter to split on [delimiter] :: Splitter a -> Delimiter a -- | What to do with delimiters (drop from output, keep as separate -- elements in output, or merge with previous or following chunks) [delimPolicy] :: Splitter a -> DelimPolicy -- | What to do with multiple consecutive delimiters [condensePolicy] :: Splitter a -> CondensePolicy -- | Drop an initial blank? [initBlankPolicy] :: Splitter a -> EndPolicy -- | Drop a final blank? [finalBlankPolicy] :: Splitter a -> EndPolicy -- | 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. defaultSplitter :: Splitter a -- | A delimiter is a list of predicates on elements, matched by some -- contiguous subsequence of a list. newtype Delimiter a Delimiter :: [a -> Bool] -> Delimiter 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. matchDelim :: Delimiter a -> [a] -> Maybe ([a], [a]) -- | What to do with delimiters? data DelimPolicy -- | Drop delimiters from the output. Drop :: DelimPolicy -- | Keep delimiters as separate chunks of the output. Keep :: DelimPolicy -- | Keep delimiters in the output, prepending them to the following chunk. KeepLeft :: DelimPolicy -- | Keep delimiters in the output, appending them to the previous chunk. KeepRight :: DelimPolicy -- | What to do with multiple consecutive delimiters? data CondensePolicy -- | Condense into a single delimiter. Condense :: CondensePolicy -- | Keep consecutive delimiters separate, but don't insert blank chunks in -- between them. DropBlankFields :: CondensePolicy -- | Insert blank chunks between consecutive delimiters. KeepBlankFields :: CondensePolicy -- | What to do with a blank chunk at either end of the list (i.e. -- when the list begins or ends with a delimiter). data EndPolicy DropBlank :: EndPolicy KeepBlank :: EndPolicy -- | Tag chunks as delimiters or text. data Chunk a Delim :: [a] -> Chunk a Text :: [a] -> Chunk a -- | Internal representation of a split list that tracks which pieces are -- delimiters and which aren't. type SplitList a = [Chunk a] -- | Untag a Chunk. fromElem :: Chunk a -> [a] -- | Test whether a Chunk is a delimiter. isDelim :: Chunk a -> Bool -- | Test whether a Chunk is text. isText :: Chunk a -> Bool -- | Given a delimiter to use, split a list into an internal representation -- with chunks tagged as delimiters or text. This transformation is -- lossless; in particular, -- --
-- concatMap fromElem (splitInternal d l) == l. --splitInternal :: Delimiter a -> [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. postProcess :: Splitter a -> SplitList a -> SplitList a -- | Drop delimiters if the DelimPolicy is Drop. doDrop :: DelimPolicy -> SplitList a -> SplitList a -- | Condense multiple consecutive delimiters into one if the -- CondensePolicy is Condense. doCondense :: CondensePolicy -> SplitList a -> SplitList a -- | Insert blank chunks between any remaining consecutive delimiters -- (unless the condense policy is DropBlankFields), and at the -- beginning or end if the first or last element is a delimiter. insertBlanks :: CondensePolicy -> SplitList a -> SplitList a -- | Insert blank chunks between consecutive delimiters. insertBlanks' :: CondensePolicy -> SplitList a -> SplitList a -- | Merge delimiters into adjacent chunks according to the -- DelimPolicy. doMerge :: DelimPolicy -> 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). mergeLeft :: SplitList a -> SplitList a -- | Merge delimiters with adjacent chunks to the left. mergeRight :: SplitList a -> SplitList a -- | Drop an initial blank chunk according to the given EndPolicy. dropInitial :: EndPolicy -> SplitList a -> SplitList a -- | Drop a final blank chunk according to the given EndPolicy. dropFinal :: EndPolicy -> SplitList a -> SplitList 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. split :: Splitter a -> [a] -> [[a]] -- | A splitting strategy that splits on any one of the given elements. For -- example: -- --
-- split (oneOf "xyz") "aazbxyzcxd" == ["aa","z","b","x","","y","","z","c","x","d"] --oneOf :: Eq a => [a] -> Splitter a -- | A splitting strategy that splits on the given list, when it is -- encountered as an exact subsequence. For example: -- --
-- 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. For example: -- --
-- split (onSublist "") "abc" == ["","","a","","b","","c"] -- 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 (:[]). onSublist :: Eq a => [a] -> Splitter a -- | A splitting strategy that splits on any elements that satisfy the -- given predicate. For example: -- --
-- split (whenElt (<0)) [2,4,-3,6,-9,1] == [[2,4],[-3],[6],[-9],[1]] --whenElt :: (a -> Bool) -> Splitter a -- | Drop delimiters from the output (the default is to keep them). For -- example, -- --
-- split (oneOf ":") "a:b:c" == ["a", ":", "b", ":", "c"] -- split (dropDelims $ oneOf ":") "a:b:c" == ["a", "b", "c"] --dropDelims :: Splitter a -> Splitter a -- | Keep delimiters in the output by prepending them to adjacent chunks. -- For example: -- --
-- split (keepDelimsL $ oneOf "xyz") "aazbxyzcxd" == ["aa","zb","x","y","zc","xd"] --keepDelimsL :: Splitter a -> Splitter a -- | Keep delimiters in the output by appending them to adjacent chunks. -- For example: -- --
-- split (keepDelimsR $ oneOf "xyz") "aazbxyzcxd" == ["aaz","bx","y","z","cx","d"] --keepDelimsR :: Splitter a -> Splitter a -- | Condense multiple consecutive delimiters into one. For example: -- --
-- split (condense $ oneOf "xyz") "aazbxyzcxd" == ["aa","z","b","xyz","c","x","d"] -- split (dropDelims $ oneOf "xyz") "aazbxyzcxd" == ["aa","b","","","c","d"] -- split (condense . dropDelims $ oneOf "xyz") "aazbxyzcxd" == ["aa","b","c","d"] --condense :: Splitter a -> Splitter a -- | Don't generate a blank chunk if there is a delimiter at the beginning. -- For example: -- --
-- split (oneOf ":") ":a:b" == ["",":","a",":","b"] -- split (dropInitBlank $ oneOf ":") ":a:b" == [":","a",":","b"] --dropInitBlank :: Splitter a -> Splitter a -- | Don't generate a blank chunk if there is a delimiter at the end. For -- example: -- --
-- split (oneOf ":") "a:b:" == ["a",":","b",":",""] -- split (dropFinalBlank $ oneOf ":") "a:b:" == ["a",":","b",":"] --dropFinalBlank :: Splitter a -> Splitter a -- | Don't generate blank chunks between consecutive delimiters. For -- example: -- --
-- split (oneOf ":") "::b:::a" == ["",":","",":","b",":","",":","",":","a"] -- split (dropInnerBlanks $ oneOf ":") "::b:::a" == ["", ":",":","b",":",":",":","a"] --dropInnerBlanks :: Splitter a -> Splitter a -- | Drop all blank chunks from the output, and condense consecutive -- delimiters into one. Equivalent to dropInitBlank . -- dropFinalBlank . condense. For example: -- --
-- split (oneOf ":") "::b:::a" == ["",":","",":","b",":","",":","",":","a"] -- split (dropBlanks $ oneOf ":") "::b:::a" == ["::","b",":::","a"] --dropBlanks :: Splitter 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. -- For example: -- --
-- split (startsWith "app") "applyapplicativeapplaudapproachapple" == ["apply","applicative","applaud","approach","apple"] --startsWith :: 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. For -- example: -- --
-- split (startsWithOneOf ['A'..'Z']) "ACamelCaseIdentifier" == ["A","Camel","Case","Identifier"] --startsWithOneOf :: 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. For example: -- --
-- split (endsWith "ly") "happilyslowlygnarlylily" == ["happily","slowly","gnarly","lily"] --endsWith :: 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. -- For example: -- --
-- split (condense $ endsWithOneOf ".,?! ") "Hi, there! How are you?" == ["Hi, ","there! ","How ","are ","you?"] --endsWithOneOf :: Eq a => [a] -> Splitter a -- | Split on any of the given elements. Equivalent to split . -- dropDelims . oneOf. For example: -- --
-- splitOneOf ";.," "foo,bar;baz.glurk" == ["foo","bar","baz","glurk"] --splitOneOf :: Eq a => [a] -> [a] -> [[a]] -- | Split on the given sublist. Equivalent to split . -- dropDelims . onSublist. For example: -- --
-- 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.) splitOn :: Eq a => [a] -> [a] -> [[a]] -- | Split on elements satisfying the given predicate. Equivalent to -- split . dropDelims . whenElt. For -- example: -- --
-- splitWhen (<0) [1,3,-4,5,7,-9,0,2] == [[1,3],[5,7],[0,2]] --splitWhen :: (a -> Bool) -> [a] -> [[a]] -- | Split into chunks terminated by the given subsequence. Equivalent to -- split . dropFinalBlank . dropDelims . -- onSublist. For example: -- --
-- endBy ";" "foo;bar;baz;" == ["foo","bar","baz"] ---- -- Note also that the lines function from Data.List is -- equivalent to endBy "\n". endBy :: Eq a => [a] -> [a] -> [[a]] -- | Split into chunks terminated by one of the given elements. Equivalent -- to split . dropFinalBlank . dropDelims . -- oneOf. For example: -- --
-- endByOneOf ";," "foo;bar,baz;" == ["foo","bar","baz"] --endByOneOf :: Eq a => [a] -> [a] -> [[a]] -- | Split into "words", with word boundaries indicated by the given -- predicate. Satisfies words === wordsBy isSpace; -- equivalent to split . dropBlanks . dropDelims -- . whenElt. For example: -- --
-- wordsBy (=='x') "dogxxxcatxbirdxx" == ["dog","cat","bird"] --wordsBy :: (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. For example: -- --
-- linesBy (=='x') "dogxxxcatxbirdxx" == ["dog","","","cat","bird",""] --linesBy :: (a -> Bool) -> [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. build :: ((a -> [a] -> [a]) -> [a] -> [a]) -> [a] -- | 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. For example: -- -- Note that chunksOf n [] is [], not -- [[]]. This is intentional, and is consistent with a recursive -- definition of chunksOf; it satisfies the property that -- --
-- chunksOf n xs ++ chunksOf n ys == chunksOf n (xs ++ ys) ---- -- whenever n evenly divides the length of xs. chunksOf :: Int -> [e] -> [[e]] -- | Split a list into chunks of the given lengths. For example: -- --
-- splitPlaces [2,3,4] [1..20] == [[1,2],[3,4,5],[6,7,8,9]] -- splitPlaces [4,9] [1..10] == [[1,2,3,4],[5,6,7,8,9,10]] -- 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. splitPlaces :: 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. For example: -- --
-- splitPlacesBlanks [2,3,4] [1..20] == [[1,2],[3,4,5],[6,7,8,9]] -- splitPlacesBlanks [4,9] [1..10] == [[1,2,3,4],[5,6,7,8,9,10]] -- 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. splitPlacesBlanks :: Integral a => [a] -> [e] -> [[e]] -- | 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 (span (not . isSpace) . dropWhile isSpace) --chop :: ([a] -> (b, [a])) -> [a] -> [b] -- | 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. -- --
-- divvy 5 5 [1..20] == [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]] ---- -- In the case where a source list's trailing elements do no fill an -- entire sublist, those trailing elements will be dropped. -- --
-- 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 priceList = -- map average divvyedPrices -- where divvyedPrices = divvy 20 1 priceList --divvy :: Int -> Int -> [a] -> [[a]] instance GHC.Show.Show Data.List.Split.Internals.DelimPolicy instance GHC.Classes.Eq Data.List.Split.Internals.DelimPolicy instance GHC.Show.Show Data.List.Split.Internals.CondensePolicy instance GHC.Classes.Eq Data.List.Split.Internals.CondensePolicy instance GHC.Show.Show Data.List.Split.Internals.EndPolicy instance GHC.Classes.Eq Data.List.Split.Internals.EndPolicy instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.List.Split.Internals.Chunk a) instance GHC.Show.Show a => GHC.Show.Show (Data.List.Split.Internals.Chunk a) -- | The Data.List.Split module contains a wide range of strategies -- for splitting lists with respect to some sort of delimiter, mostly -- implemented through a unified combinator interface. The goal is to be -- flexible yet simple. See below for usage, examples, and detailed -- documentation of all exported functions. If you want to learn about -- the implementation, see Data.List.Split.Internals. -- -- A git repository containing the source (including a module with over -- 40 QuickCheck properties) can be found at -- https://github.com/byorgey/split. module Data.List.Split -- | Split on the given sublist. Equivalent to split . -- dropDelims . onSublist. For example: -- --
-- 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.) splitOn :: Eq a => [a] -> [a] -> [[a]] -- | Split on any of the given elements. Equivalent to split . -- dropDelims . oneOf. For example: -- --
-- splitOneOf ";.," "foo,bar;baz.glurk" == ["foo","bar","baz","glurk"] --splitOneOf :: Eq a => [a] -> [a] -> [[a]] -- | Split on elements satisfying the given predicate. Equivalent to -- split . dropDelims . whenElt. For -- example: -- --
-- splitWhen (<0) [1,3,-4,5,7,-9,0,2] == [[1,3],[5,7],[0,2]] --splitWhen :: (a -> Bool) -> [a] -> [[a]] -- | Split into chunks terminated by the given subsequence. Equivalent to -- split . dropFinalBlank . dropDelims . -- onSublist. For example: -- --
-- endBy ";" "foo;bar;baz;" == ["foo","bar","baz"] ---- -- Note also that the lines function from Data.List is -- equivalent to endBy "\n". endBy :: Eq a => [a] -> [a] -> [[a]] -- | Split into chunks terminated by one of the given elements. Equivalent -- to split . dropFinalBlank . dropDelims . -- oneOf. For example: -- --
-- endByOneOf ";," "foo;bar,baz;" == ["foo","bar","baz"] --endByOneOf :: Eq a => [a] -> [a] -> [[a]] -- | Split into "words", with word boundaries indicated by the given -- predicate. Satisfies words === wordsBy isSpace; -- equivalent to split . dropBlanks . dropDelims -- . whenElt. For example: -- --
-- wordsBy (=='x') "dogxxxcatxbirdxx" == ["dog","cat","bird"] --wordsBy :: (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. For example: -- --
-- linesBy (=='x') "dogxxxcatxbirdxx" == ["dog","","","cat","bird",""] --linesBy :: (a -> Bool) -> [a] -> [[a]] -- | 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. For example: -- -- Note that chunksOf n [] is [], not -- [[]]. This is intentional, and is consistent with a recursive -- definition of chunksOf; it satisfies the property that -- --
-- chunksOf n xs ++ chunksOf n ys == chunksOf n (xs ++ ys) ---- -- whenever n evenly divides the length of xs. chunksOf :: Int -> [e] -> [[e]] -- | Split a list into chunks of the given lengths. For example: -- --
-- splitPlaces [2,3,4] [1..20] == [[1,2],[3,4,5],[6,7,8,9]] -- splitPlaces [4,9] [1..10] == [[1,2,3,4],[5,6,7,8,9,10]] -- 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. splitPlaces :: 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. For example: -- --
-- splitPlacesBlanks [2,3,4] [1..20] == [[1,2],[3,4,5],[6,7,8,9]] -- splitPlacesBlanks [4,9] [1..10] == [[1,2,3,4],[5,6,7,8,9,10]] -- 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. splitPlacesBlanks :: Integral a => [a] -> [e] -> [[e]] -- | 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 (span (not . isSpace) . dropWhile isSpace) --chop :: ([a] -> (b, [a])) -> [a] -> [b] -- | 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. -- --
-- divvy 5 5 [1..20] == [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]] ---- -- In the case where a source list's trailing elements do no fill an -- entire sublist, those trailing elements will be dropped. -- --
-- 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 priceList = -- map average divvyedPrices -- where divvyedPrices = divvy 20 1 priceList --divvy :: Int -> Int -> [a] -> [[a]] -- | A splitting strategy. data 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. defaultSplitter :: Splitter 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. split :: Splitter a -> [a] -> [[a]] -- | A splitting strategy that splits on any one of the given elements. For -- example: -- --
-- split (oneOf "xyz") "aazbxyzcxd" == ["aa","z","b","x","","y","","z","c","x","d"] --oneOf :: Eq a => [a] -> Splitter a -- | A splitting strategy that splits on the given list, when it is -- encountered as an exact subsequence. For example: -- --
-- 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. For example: -- --
-- split (onSublist "") "abc" == ["","","a","","b","","c"] -- 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 (:[]). onSublist :: Eq a => [a] -> Splitter a -- | A splitting strategy that splits on any elements that satisfy the -- given predicate. For example: -- --
-- split (whenElt (<0)) [2,4,-3,6,-9,1] == [[2,4],[-3],[6],[-9],[1]] --whenElt :: (a -> Bool) -> Splitter a -- | Drop delimiters from the output (the default is to keep them). For -- example, -- --
-- split (oneOf ":") "a:b:c" == ["a", ":", "b", ":", "c"] -- split (dropDelims $ oneOf ":") "a:b:c" == ["a", "b", "c"] --dropDelims :: Splitter a -> Splitter a -- | Keep delimiters in the output by prepending them to adjacent chunks. -- For example: -- --
-- split (keepDelimsL $ oneOf "xyz") "aazbxyzcxd" == ["aa","zb","x","y","zc","xd"] --keepDelimsL :: Splitter a -> Splitter a -- | Keep delimiters in the output by appending them to adjacent chunks. -- For example: -- --
-- split (keepDelimsR $ oneOf "xyz") "aazbxyzcxd" == ["aaz","bx","y","z","cx","d"] --keepDelimsR :: Splitter a -> Splitter a -- | Condense multiple consecutive delimiters into one. For example: -- --
-- split (condense $ oneOf "xyz") "aazbxyzcxd" == ["aa","z","b","xyz","c","x","d"] -- split (dropDelims $ oneOf "xyz") "aazbxyzcxd" == ["aa","b","","","c","d"] -- split (condense . dropDelims $ oneOf "xyz") "aazbxyzcxd" == ["aa","b","c","d"] --condense :: Splitter a -> Splitter a -- | Don't generate a blank chunk if there is a delimiter at the beginning. -- For example: -- --
-- split (oneOf ":") ":a:b" == ["",":","a",":","b"] -- split (dropInitBlank $ oneOf ":") ":a:b" == [":","a",":","b"] --dropInitBlank :: Splitter a -> Splitter a -- | Don't generate a blank chunk if there is a delimiter at the end. For -- example: -- --
-- split (oneOf ":") "a:b:" == ["a",":","b",":",""] -- split (dropFinalBlank $ oneOf ":") "a:b:" == ["a",":","b",":"] --dropFinalBlank :: Splitter a -> Splitter a -- | Don't generate blank chunks between consecutive delimiters. For -- example: -- --
-- split (oneOf ":") "::b:::a" == ["",":","",":","b",":","",":","",":","a"] -- split (dropInnerBlanks $ oneOf ":") "::b:::a" == ["", ":",":","b",":",":",":","a"] --dropInnerBlanks :: Splitter a -> Splitter a -- | Drop all blank chunks from the output, and condense consecutive -- delimiters into one. Equivalent to dropInitBlank . -- dropFinalBlank . condense. For example: -- --
-- split (oneOf ":") "::b:::a" == ["",":","",":","b",":","",":","",":","a"] -- split (dropBlanks $ oneOf ":") "::b:::a" == ["::","b",":::","a"] --dropBlanks :: Splitter 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. -- For example: -- --
-- split (startsWith "app") "applyapplicativeapplaudapproachapple" == ["apply","applicative","applaud","approach","apple"] --startsWith :: 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. For -- example: -- --
-- split (startsWithOneOf ['A'..'Z']) "ACamelCaseIdentifier" == ["A","Camel","Case","Identifier"] --startsWithOneOf :: 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. For example: -- --
-- split (endsWith "ly") "happilyslowlygnarlylily" == ["happily","slowly","gnarly","lily"] --endsWith :: 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. -- For example: -- --
-- split (condense $ endsWithOneOf ".,?! ") "Hi, there! How are you?" == ["Hi, ","there! ","How ","are ","you?"] --endsWithOneOf :: Eq a => [a] -> Splitter a