Is implementing this words function possible without a postprocessing step after folding?
If I understand correctly, your requirements include
(1) words "a b c" == words " a b c" == ["a", "b", "c"] (2) words "xa b c" == ["xa", "b", "c"] /= ["x", "a", "b", "c"] == words "x a b c"
This implies that we can not have
words = foldr step base
Indeed, if we had that, then
words "xa b c" = def words and foldr step 'x' (words "a b c") = (1) step 'x' (words " a b c") = def words and foldr words "x a b c"
and this contradicts (2).
You definitely need some post-processing after the
@chi has a wonderful argument that you cannot implement
words using "a" fold, but you did say using folds.
words = filterNull . words1 where filterNull = foldr (\xs -> if null xs then id else (xs:))  words1 = foldr (\c -> if c == ' ' then (:) else consHead c)  consHead c  = [[c]] consHead c (xs:xss) = (c:xs):xss
Both the outermost and innermost function are folds. ;-)
Yes. Eventhough it's a little tricky you may still do this job properly by using a single
foldr and nothing else if you dwell into CPS (Continuation Passing Style). I had shown a special kind of
chunksOf function previously.
In this kinds of folds our accumulator, hence the result of the fold is a function and we have to apply it to an identity kind of input so that we have the final result. So this may count as a final processing stage or not since we are using a single fold here and the type of it includes the function. Open to debate :)
ws :: String -> [String] ws str = foldr go sf str $ "" where sf :: String -> [String] sf s = if s == " " then [""] else [s] go :: Char -> (String -> [String]) -> (String -> [String]) go c f = \pc -> let (s:ss) = f [c] in case pc of "" -> dropWhile (== "") (s:ss) otherwise -> case (pc == " ", s == "") of (True, False) -> "":s:ss (True, True) -> s:ss otherwise -> (pc++s):ss λ> ws " a b c " ["a","b","c"]
sf : The initial function value to start with.
go : The iterator function
We are actually not fully utilizing the power of the CPS here since we have both the previous character
pc and the currect character
c at hand in every turn. It was very useful in the
chunksOf function mentioned above while chunking a
[[Int]] every time an ascending sequence of elements were broken.