Reputation: 139
I've been writing a really simple text game engine, and I've come across a problem: I need to be able to print a list of items in plain english. So essentially, I need a function that takes an array of strings and outputs them like how an English speaker would say them. For example:
showEnglish ["door", "car", "cat", "apple"] = "a door, a car, a cat, and an apple."
Is there a clean and fast way to do this in haskell? Thanks.
Upvotes: 1
Views: 102
Reputation: 62848
Problem 1: In English, some words get prefixed with "a", while others get "an". It ought to be possible to fix that like so:
prefixWord :: String -> String
prefixWord "" = ""
prefixWord word =
if (toLower $ head $ word) `elem` "aeiou"
then "an " ++ word
else "a " ++ word
Problem 2: Join them all together, with an "and" at the end.
joinWords :: [String] -> String
joinWords ws = (intercalate ", " (init ws)) ++ " and " ++ last ws
Put it all together:
showEnglish :: [String] -> String
showEnglish = joinWords . map prefixWord
Upvotes: 4
Reputation: 5992
You can find the indefinite determiner for a word, roughly speaking, using indefiniteDet from the minimorph package. It looks like the package is intended for just this "ad hoc" usage. It also has a function to insert commas, which unfortunately is anathema because it omits the Oxford comma. So maybe just use intercalate
instead. But:
showEnglish :: [Text] -> Text
showEnglish = commas "and" . map (\w -> indefiniteDet w `append` " " `append` w)
ghci> showEnglish ["door", "car", "cat", "apple"]
"a door, a car, a cat and an apple"
And now we don't need to hard-code simplified expectations of English morphology... we'll leave that to whoever wrote minimorph
.
Upvotes: 4