Haskell - Pig Latin Translator What improvements can I make to the following Pig Latin translator? So far, I've been wondering about the FlexibleInstances declaration, but I can't think of how to remove it (since it's required for PigLatin String in instances, which is required for me to use " " in the Monoid instance; I need the extra type argument for Functor).

{-# LANGUAGE FlexibleInstances #-}

import Control.Monad(when)
import Data.Char (toLower, toUpper)
import System.IO (hFlush, stdout)

data PigLatin a = PigLatin a

instance Monoid (PigLatin String) where
  mempty = PigLatin ""
  mappend (PigLatin a) (PigLatin b) = PigLatin $ a ++ " " ++ b

instance Functor PigLatin where
  fmap f (PigLatin x) = PigLatin $ f x

instance Show (PigLatin String) where
  show (PigLatin s) = s

data English a = English a
  deriving (Eq)

safeTail :: [a] -&gt; [a]
safeTail (_:xs) = xs
safeTail [] = []

quitCommand :: English String
quitCommand = English "\\q"

wordToPig :: English String -&gt; PigLatin String
wordToPig (English word@(x:_)) = PigLatin $ if isVowel x
                                              then word ++ "yay"
                                              else rearrangedWord ++ "ay"
    where rearrangedWord = drop (length initialConsonants) word ++ initialConsonants
          initialConsonants = takeWhile isConsonant word
          isConsonant = not . isVowel
wordToPig (English "") = PigLatin ""

isVowel :: Char -&gt; Bool
isVowel letter = letter `elem` ['a', 'e', 'i', 'o', 'u']

englishWords :: English String -&gt; [English String]
englishWords (English input) = map English $ words input

sentenceToPig :: English String -&gt; PigLatin String
sentenceToPig = fmap (capitalize . safeTail . map toLower) . foldl mappend mempty . map wordToPig . englishWords

capitalize :: String -&gt; String
capitalize (x:xs) = toUpper x : map toLower xs
capitalize [] = ""

prompt :: String -&gt; IO (English String)
prompt promptInput = do
  putStr promptInput
  hFlush stdout
  input &lt;- getLine
  return $ English input

main :: IO ()
main = do
    input &lt;- prompt "&gt; "
    when (input /= quitCommand) $ do
      print $ sentenceToPig input
      main
You can let it derive the  Functor declaration:

data PigLatin a = PigLatin a deriving Functor


foldl mappend mempty &lt;- You want fold.

break implements some of your stuff already.

I wouldn't introduce the types PigLatin a and English a in the first place. They just introduce wrapping without extra type-level structural info.

import Control.Monad (when)
import Data.Char (toLower, toUpper)
import System.IO (hFlush, stdout)
import Control.Cateogry ((&gt;&gt;&gt;)) -- flip (.)

--This turns empty words to yay, but words doesnt send empty words, right?
wordToPig :: String -&gt; String
wordToPig = break (`elem` "aeiou") &gt;&gt;&gt; \(initialConsonants, rest) -&gt;
  rest ++ initialConsonants ++ if null initialConsonants then "yay" else "ay"

-- Your pig latin rules drop the first character of each sentence at the end?
sentenceToPig :: String -&gt; String
sentenceToPig = capitalize . drop 1 . unwords . map wordToPig . words

capitalize :: String -&gt; String
capitalize (x:xs) = toUpper x : map toLower xs
capitalize [] = ""

main :: IO ()
main = do
  putStr "&gt; "
  hFlush stdout
  input &lt;- getLine
  when (input /= "\\q") $ do
    print $ sentenceToPig input
    main