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 instance
s, 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] -> [a]
safeTail (_:xs) = xs
safeTail [] = []
quitCommand :: English String
quitCommand = English "\\q"
wordToPig :: English String -> 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 -> Bool
isVowel letter = letter `elem` ['a', 'e', 'i', 'o', 'u']
englishWords :: English String -> [English String]
englishWords (English input) = map English $ words input
sentenceToPig :: English String -> PigLatin String
sentenceToPig = fmap (capitalize . safeTail . map toLower) . foldl mappend mempty . map wordToPig . englishWords
capitalize :: String -> String
capitalize (x:xs) = toUpper x : map toLower xs
capitalize [] = ""
prompt :: String -> IO (English String)
prompt promptInput = do
putStr promptInput
hFlush stdout
input <- getLine
return $ English input
main :: IO ()
main = do
input <- prompt "> "
when (input /= quitCommand) $ do
print $ sentenceToPig input
main