Consider this example (from https://codereview.stackexchange.com/questions/23456/crtitique-my-haskell-function-capitalize):
import Data.Char
capWord [] = []
cap
It's indeed not flexible enough! How would you lift a function to work on a line-by-line basis? You're going to need a newtype
wrapper for that! Like so
newtype LineByLine = LineByLine { unLineByLine :: String }
instance Lift LineByLine [String] where
up = lines . unLineByLine
down = LineByLine . unlines
But now there is no good reason to prefer the word-by-word version over the line-by-line one.
I would just use unwords . map f . words
, to me that's the idiomatic "Apply f to all the words and put them back together". If you do this more often, consider writing a function.