How can I generalize this code so that it works not only for whitespace?

Viewed 74

I made this function, that works the same way as words in Haskell,

words' [] = []
words' str = before : words' (dropWhile isSpace after) where
    (before, after) = break isSpace str

and I'm now trying to generalize it so that if I type in:

gWords'  "abcbdecefab" "ac" == ["b","bde","ef","b"]

or

gWords'  "abc(hjd(hj))jk)k" "()" == ["abc","hjd","hj","jk","k"]
1 Answers

Idiomatic Haskell is to provide a predicate (i.e., boolean function) as an argument:

wordsBy _ [] = []
wordsBy isbrk str = before : wordsBy isbrk (dropWhile isbrk after) where
    (before, after) = break isbrk str

Then, you can provide a specific predicate:

gwords' str brks = wordsBy (`elem` brks) str

To explain the predicate above:

  • the function elem returns true if its first argument can be found in the list provided as its second argument:

    elem e brks
    
  • Haskell has an alternate infix format, to treat functions as operators:

    e `elem` brks  ===  elem e brks
    
  • Haskell also has a "slice" notation to partially apply operators; you can view it as shorthand for a commonly used lambda form:

    (`elem` brks)  ===  (\ e -> e `elem` brks)
    

which gives you the desired predicate: one that returns true for characters in the string brks.

Related