diff --git a/NLP/Minimorph/English.hs b/NLP/Minimorph/English.hs
--- a/NLP/Minimorph/English.hs
+++ b/NLP/Minimorph/English.hs
@@ -1,4 +1,5 @@
-{-# LANGUAGE ViewPatterns, OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ViewPatterns      #-}
 -- TODO : learn how to use Functional Morphology instead
 
 -- | Module    : NLP.Minimorph.English
@@ -11,11 +12,16 @@
 -- Simple default rules for English morphology
 module NLP.Minimorph.English where
 
-import Data.Text ( Text )
-import qualified Data.Text as T
+import           Data.Char          (toLower, isSpace, isUpper)
+import           Data.Text          (Text)
+import qualified Data.Text          as T
 
-import NLP.Minimorph.Util
+import           NLP.Minimorph.Util
 
+-- ---------------------------------------------------------------------
+-- ** Punctuation
+-- ---------------------------------------------------------------------
+
 -- | No Oxford commas, alas.
 --
 -- > commas "and" "foo bar"       == "foo and bar"
@@ -25,26 +31,45 @@
 commas _ [x] = x
 commas et xs = T.intercalate ", " (init xs) <+> et <+> last xs
 
+-- ---------------------------------------------------------------------
+-- ** Numbers
+-- ---------------------------------------------------------------------
+
 -- | > cardinal 1 == "one"
 --   > cardinal 2 == "two"
 --   > cardinal 3 == "three"
---   > cardinal 4 == "4"
+--   > cardinal 11 == "11"
 cardinal :: Int -> Text
 cardinal n = case n of
-    1 -> "one"
-    2 -> "two"
-    3 -> "three"
+    1  -> "one"
+    2  -> "two"
+    3  -> "three"
+    4  -> "four"
+    5  -> "five"
+    6  -> "six"
+    7  -> "seven"
+    8  -> "eight"
+    9  -> "nine"
+    10 -> "ten"
     _ -> T.pack (show n)
 
--- | > cardinal 1 == "first"
---   > cardinal 2 == "second"
---   > cardinal 3 == "third"
---   > cardinal 4 == "4th"
+-- | > ordinal 1 == "first"
+--   > ordinal 2 == "second"
+--   > ordinal 3 == "third"
+--   > ordinal 11 == "11th"
+--   > ordinal 42 == "42nd"
 ordinal :: Int -> Text
 ordinal n = case n of
-    1 -> "first"
-    2 -> "second"
-    3 -> "third"
+    1  -> "first"
+    2  -> "second"
+    3  -> "third"
+    4  -> "fourth"
+    5  -> "fifth"
+    6  -> "sixth"
+    7  -> "seventh"
+    8  -> "eighth"
+    9  -> "ninth"
+    10 -> "tenth"
     n | n < 21          -> n `suf` "th"
       | n `rem` 10 == 2 -> n `suf` "nd"
       | n `rem` 10 == 3 -> n `suf` "rd"
@@ -52,6 +77,10 @@
   where
     n `suf` s = T.pack (show n) <> s
 
+-- ---------------------------------------------------------------------
+-- ** Nouns and verbs
+-- ---------------------------------------------------------------------
+
 -- | Heuristics for English plural for an unknown noun
 --
 -- > defaultNounPlural "egg"    == "eggs"
@@ -95,22 +124,81 @@
     e_final    x = (x <> "s"         , x <> "d")
     y_final    x = (T.init x <> "ies", T.init x <> "ied")
 
+-- ---------------------------------------------------------------------
+-- ** Determiners
+-- ---------------------------------------------------------------------
+
 -- | > indefiniteDet "dog"  == "a"
 --   > indefiniteDet "egg"  == "an"
 --   > indefiniteDet "ewe"  == "a"
 --   > indefiniteDet "ewok" == "an"
 --   > indefiniteDet "8th"  == "an"
 indefiniteDet :: Text -> Text
-indefiniteDet (T.toLower -> t) =
-    if useAn then "an" else "a"
+indefiniteDet t = if wantsAn t then "an" else "a"
+
+-- | True if the indefinite determiner for a word would normally be
+--   'an' as opposed to 'a'
+wantsAn :: Text -> Bool
+wantsAn t_ =
+    if startsWithAcronym t_
+       then acronymWantsAn t_
+       else useAn0 || useAn1 || useAn2
   where
-    useAn  = t `elem` [ "11", "11th" ] || useAn'
-    useAn' = case T.uncons t of
+    t      = T.toLower t_
+    useAn0 = t `elem` [ "11", "11th" ]
+    useAn1 = case T.uncons t of
                 Just ('8',_) -> True
                 Just (h,_)   -> isVowel h `butNot` hasSemivowelPrefix t
                 Nothing      -> False
+    useAn2 = case T.break isSep t of
+                (T.unpack -> [c], _) -> isLetterWithInitialVowelSound c
+                _ -> False
     x `butNot` y = x && not y
+    isSep c = isSpace c || c `elem` "-"
 
+-- | Variant of 'wantsAn' that assumes the input string is pronounced
+--   one letter at a time.
+--
+--   > wantsAn        "x-ray" == False
+--   > acronymWantsAn "x-ray" == True
+--
+--   Note that this won't do the right thing for words like @"SCUBA"@
+--   You really have to reserve it for those separate-letter acronyms
+acronymWantsAn :: Text -> Bool
+acronymWantsAn (T.toLower -> t) =
+    useAn0 || useAn1
+  where
+    useAn0 = t `elem` [ "11", "11th" ]
+    useAn1 = case T.uncons t of
+                Just ('8',_) -> True
+                Just (h,_)   -> isLetterWithInitialVowelSound h
+                Nothing      -> False
+
+-- ---------------------------------------------------------------------
+-- ** Acronyms
+-- ---------------------------------------------------------------------
+
+-- | True if all upper case from second letter and up
+--
+--   > looksLikeAcronym "DNA"  == True
+--   > looksLikeAcronym "tRNA" == True
+--   > looksLikeAcronym "DnA"  == False
+looksLikeAcronym :: Text -> Bool
+looksLikeAcronym x = T.all isUpper (T.drop 1 x)
+
+-- | True if the first word (separating on either - or space)
+--   looks like an acronym
+startsWithAcronym :: Text -> Bool
+startsWithAcronym =
+    looksLikeAcronym . firstWord
+  where
+    firstWord = fst . T.break isSep
+    isSep c   = isSpace c || c `elem` "-"
+
+-- ---------------------------------------------------------------------
+-- ** Sounds
+-- ---------------------------------------------------------------------
+
 -- | Ends with a sh sound
 hasSibilantSuffix :: Text -> Bool
 hasSibilantSuffix x = any (`T.isSuffixOf` x) ["x","s","ch","sh"]
@@ -126,7 +214,18 @@
 
 -- | Is a vowel
 isVowel :: Char -> Bool
-isVowel = (`elem` "aeiouAEIOU")
+isVowel = (`elem` "aeiou") . toLower
+
+-- | Letters that when pronounced independently in English sound like they
+--   begin with vowels
+--
+--   > isLetterWithInitialVowelSound 'r' == True
+--   > isLetterWithInitialVowelSound 'k' == False
+--
+--   (In the above, @'r'@ is pronounced @"are"@, but @'k'@ is pronounced
+--   @"kay"@)
+isLetterWithInitialVowelSound :: Char -> Bool
+isLetterWithInitialVowelSound = (`elem` "aeioufhlmnrsx") . toLower
 
 -- | Is a consonant
 isConsonant :: Char -> Bool
diff --git a/minimorph.cabal b/minimorph.cabal
--- a/minimorph.cabal
+++ b/minimorph.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                minimorph
-version:             0.1.1.0
+version:             0.1.3.0
 synopsis:            English spelling functions with an emphasis on simplicity.
 description:         A set of simplistic functions capturing the more regular
                      parts of English spelling (for generation, not parsing).
@@ -25,7 +25,7 @@
 
 source-repository head
   type:     darcs
-  location: http://darcsden.com/kowey/minimorph
+  location: http://hub.darcs.net/kowey/minimorph
 
 library
   exposed-modules:     NLP.Minimorph.English
