úÎÛhÖèT      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS+(c) Brent Yorgey, Louis Wasserman 2008-2012BSD-style (see LICENSE) Brent Yorgey <byorgey@gmail.com>stable Haskell 2010Safe@dInternal representation of a split list that tracks which pieces are delimiters and which aren't.!Tag chunks as delimiters or text.<What to do with a blank chunk at either end of the list (i.e.0 when the list begins or ends with a delimiter).0What to do with multiple consecutive delimiters?!Condense into a single delimiter. ]Keep consecutive delimiters separate, but don't insert blank chunks in between them. 9Insert blank chunks between consecutive delimiters. What to do with delimiters?  Drop delimiters from the output. 4Keep delimiters as separate chunks of the output.LKeep delimiters in the output, prepending them to the following chunk.GKeep delimiters in the output, appending them to the previous chunk.eA delimiter is a list of predicates on elements, matched by some contiguous subsequence of a list.A splitting strategy.What delimiter to split on‡What to do with delimiters (drop from output, keep as separate elements in output, or merge with previous or following chunks)2What to do with multiple consecutive delimitersDrop an initial blank?Drop a final blank?í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 % should normally not be used; use +, ,, or -' instead, which are the same as the $ with just the delimiter overridden.The  strategy with any delimiter gives a maximally information-preserving splitting strategy, in the sense that (a) taking the Th of the output yields the original list, and (b) given only the output list, we can reconstruct a ¯ 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.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.Untag a .Test whether a  is a delimiter.Test whether a  is text.§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,  U  ( d l) == l. Â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 .!Drop delimiters if the   is  ."<Condense multiple consecutive delimiters into one if the  is .#cInsert blank chunks between any remaining consecutive delimiters (unless the condense policy is  N), and at the beginning or end if the first or last element is a delimiter.$3Insert blank chunks between consecutive delimiters.%7Merge delimiters into adjacent chunks according to the  .&¹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).'2Merge delimiters with adjacent chunks to the left.(3Drop an initial blank chunk according to the given .)0Drop a final blank chunk according to the given .*SSplit a list according to the given splitting strategy. This is how to "run" a 4 that has been built using the other combinators.+SA splitting strategy that splits on any one of the given elements. For example: Psplit (oneOf "xyz") "aazbxyzcxd" == ["aa","z","b","x","","y","","z","c","x","d"],tA 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"]dHowever, if you want to break a list into singleton elements like this, you are better off using E 1, or better yet, V (:[]).-cA splitting strategy that splits on any elements that satisfy the given predicate. For example: Asplit (whenElt (<0)) [2,4,-3,6,-9,1] == [[2,4],[-3],[6],[-9],[1]].NDrop delimiters from the output (the default is to keep them). For example, psplit (oneOf ":") "a:b:c" == ["a", ":", "b", ":", "c"] split (dropDelims $ oneOf ":") "a:b:c" == ["a", "b", "c"]/UKeep delimiters in the output by prepending them to adjacent chunks. For example: Osplit (keepDelimsL $ oneOf "xyz") "aazbxyzcxd" == ["aa","zb","x","y","zc","xd"]0SKeep delimiters in the output by appending them to adjacent chunks. For example: Osplit (keepDelimsR $ oneOf "xyz") "aazbxyzcxd" == ["aaz","bx","y","z","cx","d"]1@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"]2WDon't generate a blank chunk if there is a delimiter at the beginning. For example: nsplit (oneOf ":") ":a:b" == ["",":","a",":","b"] split (dropInitBlank $ oneOf ":") ":a:b" == [":","a",":","b"]3PDon't generate a blank chunk if there is a delimiter at the end. For example: osplit (oneOf ":") "a:b:" == ["a",":","b",":",""] split (dropFinalBlank $ oneOf ":") "a:b:" == ["a",":","b",":"]4KDon't generate blank chunks between consecutive delimiters. For example: ›split (oneOf ":") "::b:::a" == ["",":","",":","b",":","",":","",":","a"] split (dropInnerBlanks $ oneOf ":") "::b:::a" == ["", ":",":","b",":",":",":","a"]5gDrop all blank chunks from the output, and condense consecutive delimiters into one. Equivalent to 2 . 3 . 1. For example: ‰split (oneOf ":") "::b:::a" == ["",":","",":","b",":","",":","",":","a"] split (dropBlanks $ oneOf ":") "::b:::a" == ["::","b",":::","a"]6ŠMake a strategy that splits a list into chunks that all start with the given subsequence (except possibly the first). Equivalent to 2 . / . ,. For example: wsplit (startsWith "app") "applyapplicativeapplaudapproachapple" == ["apply","applicative","applaud","approach","apple"]7ŽMake a strategy that splits a list into chunks that all start with one of the given elements (except possibly the first). Equivalent to 2 . / . +. For example: ^split (startsWithOneOf ['A'..'Z']) "ACamelCaseIdentifier" == ["A","Camel","Case","Identifier"]8‡Make a strategy that splits a list into chunks that all end with the given subsequence, except possibly the last. Equivalent to 3 . 0 . ,. For example: Wsplit (endsWith "ly") "happilyslowlygnarlylily" == ["happily","slowly","gnarly","lily"]9‹Make a strategy that splits a list into chunks that all end with one of the given elements, except possibly the last. Equivalent to 3 . 0 . +. For example: osplit (condense $ endsWithOneOf ".,?! ") "Hi, there! How are you?" == ["Hi, ","there! ","How ","are ","you?"]:3Split on any of the given elements. Equivalent to * . . . +. For example: CsplitOneOf ";.," "foo,bar;baz.glurk" == ["foo","bar","baz","glurk"];+Split on the given sublist. Equivalent to * . . . ,. 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  function from  Data.List , that is,  intercalate x . splitOn x === id; x .  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 xm does not occur in any elements of the input list. Working out why is left as an exercise for the reader.)<DSplit on elements satisfying the given predicate. Equivalent to * . . . -. For example: 9splitWhen (<0) [1,3,-4,5,7,-9,0,2] == [[1,3],[5,7],[0,2]]?HSplit into chunks terminated by the given subsequence. Equivalent to * . 3 . . . ,. For example: /endBy ";" "foo;bar;baz;" == ["foo","bar","baz"]Note also that the W function from  Data.List is equivalent to ? "\n".@LSplit into chunks terminated by one of the given elements. Equivalent to * . 3 . . . +. For example: 5endByOneOf ";," "foo;bar,baz;" == ["foo","bar","baz"]BYSplit into "words", with word boundaries indicated by the given predicate. Satisfies  === wordsBy ; equivalent to * . 5 . . . -. For example: :wordsBy (=='x') "dogxxxcatxbirdxx" == ["dog","cat","bird"]CXSplit into "lines", with line boundaries indicated by the given predicate. Satisfies W === linesBy (=='\n'); equivalent to * . 3 . . . -. For example: ClinesBy (=='x') "dogxxxcatxbirdxx" == ["dog","","","cat","bird",""]D7Standard build function, specialized to building lists.&Usually build is given the rank-2 type 3build :: (forall b. (a -> b -> b) -> b -> b) -> [a]but since we only use it when  (b ~ [a])l, we give it the more restricted type signature in order to avoid needing a non-Haskell2010 extension.HNote that the 0.1.4.3 release of this package did away with a custom build2 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 splitX 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.EE nK splits a list into length-n pieces. The last piece will be shorter if n7 does not evenly divide the length of the list. If n <= 0, E n l: returns an infinite list of empty lists. For example: Note that E n [] is [], not [[]]O. This is intentional, and is consistent with a recursive definition of E ; it satisfies the property that 7chunksOf n xs ++ chunksOf n ys == chunksOf n (xs ++ ys) whenever n evenly divides the length of xs.H;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.I9Split a list into chunks of the given lengths. Unlike HÿU, 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 H.Jÿ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.MFor 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)K>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. Qdivvy 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]]GAs 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 priceListL  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKL   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK:   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK+(c) Brent Yorgey, Louis Wasserman 2008-2012BSD-style (see LICENSE) Brent Yorgey <byorgey@gmail.com>stable Haskell 2010Safe#*+,-./0123456789:;<=>?@ABCEFGHIJK#;:<?@BCEHIJK*+,-./0123456789=>AGFX      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\Z[]Z^_Z`ab#split-0.2.3.2-1dCEe3bkR6E9uyZt6jsXKData.List.Split.Internals Data.List intercalatewords Data.CharisSpaceData.List.Split SplitListChunkDelimText EndPolicy DropBlank KeepBlankCondensePolicyCondenseDropBlankFieldsKeepBlankFields DelimPolicyDropKeepKeepLeft KeepRight DelimiterSplitter delimiter delimPolicycondensePolicyinitBlankPolicyfinalBlankPolicydefaultSplitter matchDelimfromElemisDelimisText splitInternal breakDelim postProcessdoDrop doCondense insertBlanks insertBlanks'doMerge mergeLeft mergeRight dropInitial dropFinalsplitoneOf onSublistwhenElt dropDelims keepDelimsL keepDelimsRcondense dropInitBlankdropFinalBlankdropInnerBlanks dropBlanks startsWithstartsWithOneOfendsWith endsWithOneOf splitOneOfsplitOn splitWhensepBy sepByOneOfendBy endByOneOf unintercalatewordsBylinesBybuildchunksOfchunk splitEvery splitPlacessplitPlacesBlankschopdivvy$fEqDelimPolicy$fShowDelimPolicy$fEqCondensePolicy$fShowCondensePolicy $fEqEndPolicy$fShowEndPolicy $fShowChunk $fEqChunkbase Data.Foldableconcat concatMapGHC.Basemap Data.OldListlines