minimorph 0.1.3.0 → 0.1.4.0
raw patch · 4 files changed
+99/−62 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ NLP.Minimorph.English: anNumerals :: [Text]
+ NLP.Minimorph.English: defaultPossesive :: Text -> Text
+ NLP.Minimorph.English: hasCoSuffix :: Text -> Bool
+ NLP.Minimorph.English: ordinalNotSpelled :: Int -> Text
+ NLP.Minimorph.Util: showT :: Show a => a -> Text
Files
- NLP/Minimorph/English.hs +83/−50
- NLP/Minimorph/Number.hs +1/−1
- NLP/Minimorph/Util.hs +10/−6
- minimorph.cabal +5/−5
NLP/Minimorph/English.hs view
@@ -51,8 +51,21 @@ 8 -> "eight" 9 -> "nine" 10 -> "ten"- _ -> T.pack (show n)+ _ -> showT n +-- | > ordinalNotSpelled 1 == "1st"+-- > ordinalNotSpelled 2 == "2nd"+-- > ordinalNotSpelled 11 == "11th"+ordinalNotSpelled :: Int -> Text+ordinalNotSpelled k = case abs k `rem` 100 of+ n | n > 3 && n < 21 -> k `suf` "th"+ | n `rem` 10 == 1 -> k `suf` "st"+ | n `rem` 10 == 2 -> k `suf` "nd"+ | n `rem` 10 == 3 -> k `suf` "rd"+ | otherwise -> k `suf` "th"+ where+ num `suf` s = showT num <> s+ -- | > ordinal 1 == "first" -- > ordinal 2 == "second" -- > ordinal 3 == "third"@@ -70,18 +83,13 @@ 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"- | otherwise -> n `suf` "th"- where- n `suf` s = T.pack (show n) <> s+ k -> ordinalNotSpelled k -- --------------------------------------------------------------------- -- ** Nouns and verbs -- --------------------------------------------------------------------- --- | Heuristics for English plural for an unknown noun+-- | Heuristics for English plural for an unknown noun. -- -- > defaultNounPlural "egg" == "eggs" -- > defaultNounPlural "patch" == "patches"@@ -90,44 +98,64 @@ -- > defaultNounPlural "thesis" == "theses" -- -- http://www.paulnoll.com/Books/Clear-English/English-plurals-1.html+-- http://en.wikipedia.org/wiki/English_plural defaultNounPlural :: Text -> Text defaultNounPlural x | "is" `T.isSuffixOf` x = thesis- | hasSibilantSuffix x = es- | hasCySuffix x = y_ies- | "f" `T.isSuffixOf` x = f_ves+ | hasSibilantSuffix x = sibilant_o+ | hasCoSuffix x = sibilant_o+ | hasCySuffix x = y_final+ | "f" `T.isSuffixOf` x = f_final | otherwise = plain where- plain = x <> "s"- es = x <> "es"- y_ies = T.init x <> "ies"- f_ves = T.init x <> "ves"- thesis = tDropEnd 2 x <> "es"+ plain = x <> "s"+ sibilant_o = x <> "es"+ y_final = T.init x <> "ies"+ f_final = T.init x <> "ves"+ thesis = tDropEnd 2 x <> "es" -- | Heuristics for 3rd person singular and past participle--- for an unknown regular verb+-- for an unknown regular verb. Doubling of final consonants+-- can be handled via a table of (partially) irrefular verbs. -- -- > defaultVerbStuff "walk" == ("walks", "walked") -- > defaultVerbStuff "push" == ("pushes", "pushed") -- > defaultVerbStuff "play" == ("plays", "played") -- > defaultVerbStuff "cry" == ("cries", "cried") defaultVerbStuff :: Text -> (Text, Text)-defaultVerbStuff v- | hasSibilantSuffix v = sibilant_o v- | "o" `T.isSuffixOf` v = sibilant_o v- | "e" `T.isSuffixOf` v = e_final v- | hasCySuffix v = y_final v- | otherwise = plain v+defaultVerbStuff x+ | hasSibilantSuffix x = sibilant_o+ | hasCoSuffix x = sibilant_o+ | hasCySuffix x = y_final+ | "e" `T.isSuffixOf` x = e_final+ | otherwise = plain where- plain x = (x <> "s" , x <> "ed")- sibilant_o x = (x <> "es" , x <> "ed")- e_final x = (x <> "s" , x <> "d")- y_final x = (T.init x <> "ies", T.init x <> "ied")+ plain = (x <> "s" , x <> "ed")+ sibilant_o = (x <> "es" , x <> "ed")+ e_final = (x <> "s" , x <> "d")+ y_final = (T.init x <> "ies", T.init x <> "ied") +-- | Heuristics for a possesive form for an unknown noun.+--+-- > defaultPossesive "pass" == "pass'"+-- > defaultPossesive "SOS" == "SOS'"+-- > defaultPossesive "Mr Blinkin'" == "Mr Blinkin's"+-- > defaultPossesive "cry" == "cry's"+defaultPossesive :: Text -> Text+defaultPossesive t =+ case T.last t of+ 's' -> t <> "'"+ 'S' -> t <> "'"+ '\'' -> t <> "s"+ _ -> t <> "'s"+ -- --------------------------------------------------------------------- -- ** Determiners -- --------------------------------------------------------------------- +anNumerals :: [Text]+anNumerals = [ "11", "11th", "18", "18th" ]+ -- | > indefiniteDet "dog" == "a" -- > indefiniteDet "egg" == "an" -- > indefiniteDet "ewe" == "a"@@ -137,22 +165,20 @@ 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'+-- 'an' as opposed to 'a'. wantsAn :: Text -> Bool wantsAn t_ = if startsWithAcronym t_ then acronymWantsAn t_- else useAn0 || useAn1 || useAn2+ else useAn0 || useAn1 where- t = T.toLower t_- useAn0 = t `elem` [ "11", "11th" ]+ t = fst $ T.break isSep $ T.toLower t_+ useAn0 = t `elem` anNumerals useAn1 = case T.uncons t of Just ('8',_) -> True- Just (h,_) -> isVowel h `butNot` hasSemivowelPrefix t+ Just (h, "") -> isLetterWithInitialVowelSound h+ 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` "-" @@ -162,13 +188,13 @@ -- > 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+-- 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" ]+ useAn0 = t `elem` anNumerals useAn1 = case T.uncons t of Just ('8',_) -> True Just (h,_) -> isLetterWithInitialVowelSound h@@ -178,16 +204,18 @@ -- ** Acronyms -- --------------------------------------------------------------------- --- | True if all upper case from second letter and up+-- | True if all upper case from second letter and up. -- -- > looksLikeAcronym "DNA" == True -- > looksLikeAcronym "tRNA" == True+-- > looksLikeAcronym "x" == False -- > looksLikeAcronym "DnA" == False looksLikeAcronym :: Text -> Bool-looksLikeAcronym x = T.all isUpper (T.drop 1 x)+looksLikeAcronym "" = False+looksLikeAcronym x = T.all isUpper (if T.length x > 1 then T.drop 1 x else x) -- | True if the first word (separating on either - or space)--- looks like an acronym+-- looks like an acronym. startsWithAcronym :: Text -> Bool startsWithAcronym = looksLikeAcronym . firstWord@@ -199,34 +227,39 @@ -- ** Sounds -- --------------------------------------------------------------------- --- | Ends with a sh sound+-- | Ends with a sh sound. hasSibilantSuffix :: Text -> Bool-hasSibilantSuffix x = any (`T.isSuffixOf` x) ["x","s","ch","sh"]+hasSibilantSuffix x = any (`T.isSuffixOf` x) ["x","s","ch","sh","z","j"] --- | Starts with a semivowel+-- | Starts with a semivowel. hasSemivowelPrefix :: Text -> Bool hasSemivowelPrefix ls = any (`T.isPrefixOf` ls) ["y","w","eu","ewe"] --- | Last two letters are a consonant and 'y'+-- | Last two letters are a consonant and 'y'. hasCySuffix :: Text -> Bool hasCySuffix (T.unpack . tTakeEnd 2 -> [x, 'y']) = isConsonant x hasCySuffix _ = False --- | Is a vowel+-- | Last two letters are a consonant and 'o'.+hasCoSuffix :: Text -> Bool+hasCoSuffix (T.unpack . tTakeEnd 2 -> [x, 'o']) = isConsonant x+hasCoSuffix _ = False++-- | Is a vowel. isVowel :: Char -> Bool isVowel = (`elem` "aeiou") . toLower -- | Letters that when pronounced independently in English sound like they--- begin with vowels+-- begin with vowels. -- -- > isLetterWithInitialVowelSound 'r' == True -- > isLetterWithInitialVowelSound 'k' == False -- -- (In the above, @'r'@ is pronounced @"are"@, but @'k'@ is pronounced--- @"kay"@)+-- @"kay"@.) isLetterWithInitialVowelSound :: Char -> Bool-isLetterWithInitialVowelSound = (`elem` "aeioufhlmnrsx") . toLower+isLetterWithInitialVowelSound = (`elem` "aeiofhlmnrsx") . toLower --- | Is a consonant+-- | Is a consonant. isConsonant :: Char -> Bool isConsonant = not . isVowel
NLP/Minimorph/Number.hs view
@@ -2,7 +2,7 @@ import Data.Text ( Text ) --- | Singular and Plural+-- | Singular and Plural. data SingPlu a = SP { sg :: a , pl :: a
NLP/Minimorph/Util.hs view
@@ -6,27 +6,31 @@ -- Stability : experimental -- Portability : portable ----- Utility functions probably internal to minimorph+-- Text utility functions. module NLP.Minimorph.Util where import Data.Text ( Text ) import qualified Data.Text as T --- | @tTakeEnd n t@ returns the last @n@ letters of @t@+-- | @tTakeEnd n t@ returns the last @n@ letters of @t@. tTakeEnd :: Int -> Text -> Text tTakeEnd n t = T.drop (T.length t - n) t --- | @tDropEnd n t@ drops the last @n@ letters of @t@+-- | @tDropEnd n t@ drops the last @n@ letters of @t@. tDropEnd :: Int -> Text -> Text tDropEnd n x = T.take (T.length x - n) x --- | Identical to 'T.append'+-- | Identical to 'T.append'. (<>) :: Text -> Text -> Text t1 <> t2 = t1 `T.append` t2 -- | Separated by space unless one of them is empty (in which case just--- the non-empty one)+-- the non-empty one). (<+>) :: Text -> Text -> Text t1 <+> t2 | T.null t1 = t2 | T.null t2 = t1- | otherwise = t1 `T.append` " " `T.append` t2+ | otherwise = t1 <> " " <> t2++-- | Show a value in Text format.+showT :: Show a => a -> Text+showT = T.pack . show
minimorph.cabal view
@@ -1,8 +1,8 @@--- Initial minimorph.cabal generated by cabal init. For further +-- Initial minimorph.cabal generated by cabal init. For further -- documentation, see http://haskell.org/cabal/users-guide/ name: minimorph-version: 0.1.3.0+version: 0.1.4.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).@@ -10,7 +10,7 @@ irregular nouns/verbs. This package is not meant to provide anything resembling a full account of English morphology (something like Functional Morphology or sequor could be- better suited). The main goal is to provide something cheap+ better suited). The main goal is to provide something cheap and cheerful with no learning curve, that you can use until your application calls for more robustness. homepage: http://darcsden.com/kowey/minimorph@@ -18,7 +18,7 @@ license-file: LICENSE author: Eric Kow maintainer: eric.kow@gmail.com--- copyright: +-- copyright: category: Natural Language Processing build-type: Simple cabal-version: >=1.8@@ -31,7 +31,7 @@ exposed-modules: NLP.Minimorph.English NLP.Minimorph.Number NLP.Minimorph.Util- -- other-modules: + -- other-modules: build-depends: base < 5 , text