<div>I would like to propose the following function for inclusion in Data.List</div><div><br></div><div>chop :: (a -> (b, [a]) -> [a] -> [b]</div><div>chop _ [] = []</div><div>chop f as = b : chop f as'</div><div>
where (b, as') = f as</div><div><br></div><div>It's commonly occuring recursion pattern. Typically chop is called</div><div>with some function that will consume an initial prefix of the list</div><div>and produce a value and the rest of the list.</div>
<div><br></div><div>The function is clearly related to unfoldr, but I find it more</div><div>convenient to use in a lot of cases.</div><div><br></div><div>Some examples</div><div>-------------</div><div><br></div><div>-- From Data.List</div>
<div>group :: (Eq a) => [a] -> [[a]]</div><div>group = chop (\ xs@(x:_) -> span (==x) xs)</div><div><br></div><div>-- From Data.List</div><div>words :: String -> [String]</div><div>words = filter (not . null) . chop (span (not . isSpace) . dropWhile isSpace)</div>
<div><br></div><div>-- From Data.List</div><div>lines :: String -> [String]</div><div>lines = chop ((id *** dropNL) . span (/= '\n'))</div><div> where dropNL ('\n':s) = s; dropNL s = s</div><div><br></div>
<div>-- From Data.List</div><div>tails :: [a] -> [[a]]</div><div>tails = (++ [[]]) . chop (\ xs@(_:xs') -> (xs, xs'))</div><div><br></div><div>-- From Data.List</div><div>map f = chop (\ (x:xs) -> (f x, xs))</div>
<div><br></div><div>-- Split a list into a list of list with length n.</div><div>splitEveryN n = chop (splitAt n)</div><div><br></div><div>-- Simple Haskell tokenizer</div><div>tokenize = chop (head . lex)</div><div><br></div>
<div><br></div><div>History</div><div>-------</div><div><br></div><div>I first encountered this function around 1981 when I was talking to</div><div>Sören Holmström about this recursion pattern and he said that he</div><div>
had also observed it and he called the function chopList.</div><div>Ever since then I've used chopList a lot, but unfortunately I always</div><div>have to make my own definition of this common function.</div><div><br>
</div>