Consider this example (from https://codereview.stackexchange.com/questions/23456/crtitique-my-haskell-function-capitalize):
import Data.Char
capWord [] = []
cap
I'd say the best answer is "no, because abstracting over that doesn't buy you anything". In fact your solution is far less flexible: there can be only one instance of Lift String [String]
in scope and there are more ways to split string into a list of strings than just words/unwords
(which means you'll start throwing newtypes or even more arcane extensions into the mix). Keep it simple — the original capitalize
is just fine the way it is.
Or, if you really insist:
lifted :: (a -> b, b -> a) -> (b -> b) -> a -> a
lifted (up, down) f = down . f . up
onWords = lifted (words, unwords)
onLines = lifted (lines, unlines)
capitalize = onWords $ map capWord
Conceptually the same thing as your typeclass, except without abusing typeclass machinery so much.