Find acronyms in Haskell Related to this code golf challenge, I tried to find acronyms with Haskell without using regular expressions.

The idea is to split the input string at every space or dash before finally gluing the heads of these parts together, if they are uppercase.

This is my code:

import System.Environment
import Data.Char

main :: IO ()
main = do
    [inp] &lt;- getArgs -- get input from the command line
    putStrLn $ getAcronym inp

getAcronym :: String -&gt; String
getAcronym [] = []
getAcronym s  = foldr step [] parts
    where parts = split isWordSep s -- split into words
          step x acc = if isUpper . head $ x
                       then head x : acc else acc -- glue uppercase heads together

split :: (a -&gt; Bool) -&gt; [a] -&gt; [[a]]
split p []       = []
split p s@(x:xs)
  | p x       = split p xs -- discard trailing white spaces
  | otherwise = w : split p r -- continue with the rest
      where (w, r) = break p s -- seperate prefix

isWordSep :: Char -&gt; Bool
isWordSep x = x == ' ' || x == '-'


As this really seems like a very simple problem, my code looks like way too much complexity.

Do you have any helpful improvements to slim down my code?
Since you asked for help slimming down your code, I'll give you some hints that might otherwise be inadvisable.


Don't use do-notation. In fact, you can replace

main :: IO ()
main = do
    [inp] &lt;- getArgs -- get input from the command line
    putStrLn $ getAcronym inp


with

main :: IO ()
main = putStrLn =&lt;&lt; (fmap (getAcronym . head) getArgs)

I'd replace isWordSep to take advantage of pattern matching. As an example:

isWordSep :: Char -&gt; Bool
isWordSep ' ' = True
isWordSep '-' = True
isWordSep _   = False

Consider using a parser library. Monadic parser combinators are quite nice, and they accomplish what you'd probably use regular expression for, but with far nicer error messages and type safety. Here's one example using megaparsec:

import           Control.Monad
import           Data.Void
import           Text.Megaparsec
import           Text.Megaparsec.Char

type Parser = Parsec Void String

uppercaseWord :: Parser Char
uppercaseWord = do
    h &lt;- upperChar
    many $ noneOf "- "
    pure h

acronymP :: Parser String
acronymP = some $ do
    w &lt;- uppercaseWord
    void (oneOf " -") &lt;|&gt; eof
    pure w

acronym :: String -&gt; IO ()
acronym = parseTest acronymP


You can unpack the do-notation to get:

acronym :: String -&gt; IO ()
acronym = parseTest (acronymP :: Parser String)
    where
        acronymP = some (uppercaseWord &gt;&gt;= ((void (oneOf " -") &lt;|&gt; eof) &gt;&gt;) . pure)
        uppercaseWord = upperChar &gt;&gt;= ((many (noneOf "- ") &gt;&gt;) . pure)


which, surprisingly enough, does indeed work.