packages feed

Sonnex 0.1.0.2 → 0.1.0.3

raw patch · 4 files changed

+214/−49 lines, 4 filesdep +QuickCheckPVP ok

version bump matches the API change (PVP)

Dependencies added: QuickCheck

API changes (from Hackage documentation)

Files

README.md view
@@ -14,7 +14,7 @@ - C ← ch - d ← d, dd - e ← e, eu-- é ← ê, é, è, ai, ei+- E ← ê, é, è, ai, ei - f ← f, ff, ph - g ← gu - i ← î, i, ille
Sonnex.cabal view
@@ -1,5 +1,5 @@ name:                Sonnex-version:             0.1.0.2+version:             0.1.0.3 synopsis:            Sonnex is an alternative to Soundex for french language description: @@ -29,6 +29,13 @@   hs-source-dirs:      src   ghc-options:         -Wall   default-language:    Haskell2010++test-suite testMain+    build-depends: QuickCheck -any, base >=4.7 && <4.8+    type: exitcode-stdio-1.0+    main-is: test-sonnex.hs+    buildable: True+    hs-source-dirs: src test  source-repository head   type: git
src/Text/Sonnex.hs view
@@ -22,7 +22,7 @@ - C ← ch - d ← d, dd - e ← e, eu-- é ← ê, é, è, ai, ei+- E ← ê, é, è, ai, ei - f ← f, ff, ph - g ← gu - i ← î, i, ille@@ -92,22 +92,23 @@  -- Apostroph is ignored/silent sonx ('\'':cs) = sonx cs+sonx ('’':cs) = sonx cs  -- Starting with 'a' sonx "a" = "a"-sonx "aient" = "é"+sonx "aient" = "E" sonx "ain" = "1" sonx ('a':'i':'n':v:cs)-    | isVowel v = 'é':sonx (v:cs)+    | isVowel v = 'E':sonx (v:cs)     | otherwise = '1':sonx (v:cs)-sonx "ais" = "é"+sonx "ais" = "E" sonx ('a':'i':'s':v:cs)-    | v == 's'  = 'é':'s':sonx cs-    | isVowel v = 'é':'z':sonx (v:cs)-    | otherwise = 'é':'s':sonx (v:cs)+    | v == 's'  = 'E':'s':sonx cs+    | isVowel v = 'E':'z':sonx (v:cs)+    | otherwise = 'E':'s':sonx (v:cs) sonx "ail" = "ai" sonx ('a':'i':'l':'l':cs) = 'a':'i':sonx cs-sonx ('a':'i':cs) = 'é':sonx cs+sonx ('a':'i':cs) = 'E':sonx cs sonx ('a':'m':'m':cs) = 'a':'m':sonx cs sonx ('a':'m':c:cs)     | c == 'm'  = 'a':'m':sonx cs@@ -118,16 +119,19 @@     | c == 'n'  = 'a':'n':sonx cs     | isVowel c = 'a':'n':sonx (c:cs)     | otherwise = '2':sonx (c:cs)+sonx "assent" = "as" sonx ('a':'s':c:cs)     | c == 's'   = 'a':'s':sonx cs     | isConson c = 'a':'s':sonx (c:cs)     | otherwise  = 'a':'z':sonx (c:cs) sonx ('a':'u':cs) = 'o':sonx cs-sonx "ay" = "é"-sonx "ays" = "é"+sonx "ay" = "E"+sonx "ays" = "E"  sonx ('à':cs) = 'a':sonx cs-sonx ('â':cs) = 'a':sonx cs+sonx ('â':c:cs)+    | c == 't'  = 'a':sonx ('t':cs)+    | otherwise = 'a':sonx(c:cs)  -- Starting with 'b' sonx "b" = ""@@ -168,48 +172,50 @@  -- Starting with 'e' sonx "e" = ""-sonx "ec" = "éc"-sonx "ef" = "éf"+sonx "ec" = "Ec"+sonx "ef" = "Ef" sonx "eaux" = "o" sonx ('e':'a':'n':'n':cs) = 'a':'n':sonx cs sonx ('e':'a':'n':cs) = '2':sonx cs sonx ('e':'a':'u':cs) = 'o':sonx cs-sonx ('e':'f':'f':cs) = 'é':'f':sonx cs+sonx ('e':'f':'f':cs) = 'E':'f':sonx cs+sonx ('e':'g':'m':cs) = 'E':sonx ('g':'m':cs) sonx "ein" = "1" sonx ('e':'i':'n':c:cs)-    | c == 'n'  = 'é':'n':sonx cs-    | isVowel c = 'é':'n':sonx (c:cs)+    | c == 'n'  = 'E':'n':sonx cs+    | isVowel c = 'E':'n':sonx (c:cs)     | otherwise = '1':sonx (c:cs)-sonx ('e':'i':cs) = 'é':sonx cs-sonx ('e':'l':'l':cs) = 'é':'l':sonx cs+sonx ('e':'i':cs) = 'E':sonx cs+sonx ('e':'l':'l':cs) = 'E':'l':sonx cs sonx ('e':'l':c:cs)-    | isConson c = 'é':sonx ('l':c:cs)+    | isConson c = 'E':sonx ('l':c:cs)     | otherwise  = 'e':sonx ('l':c:cs)-sonx ('e':'m':'m':cs) = 'é':'m':sonx cs+sonx ('e':'m':'m':cs) = 'E':'m':sonx cs sonx ('e':'m':'p':cs) = '2':sonx cs-sonx ('e':'n':'n':cs) = 'é':'n':sonx cs+sonx ('e':'n':'n':cs) = 'E':'n':sonx cs sonx "en" = "2" sonx ('e':'n':c:cs)     | isVowel c = 'e':'n':sonx (c:cs)     | otherwise = '2':sonx (c:cs)-sonx "er" = "é"-sonx "ert" = "ér"-sonx ('e':'r':'r':cs) = 'é':'r':sonx cs-sonx ('e':'r':'f':cs) = 'é':'r':sonx ('f':cs)+sonx "er" = "E"+sonx "ert" = "Er"+sonx ('e':'r':'r':cs) = 'E':'r':sonx cs+sonx ('e':'r':'f':cs) = 'E':'r':sonx ('f':cs) sonx "es" = ""-sonx ('e':'s':'c':'h':cs) = 'é':'C':sonx cs+sonx ('e':'s':'c':'h':cs) = 'E':'C':sonx cs+sonx "essent" = "Es" sonx ('e':'s':c:cs)-    | c == 'h'   = 'é':sonx ('h':cs)-    | c == 'n'   = 'é':sonx ('n':cs)-    | c == 's'   = 'é':'s':sonx cs-    | isConson c = 'é':'s':sonx (c:cs)+    | c == 'h'   = 'E':sonx ('h':cs)+    | c == 'n'   = 'E':sonx ('n':cs)+    | c == 's'   = 'E':'s':sonx cs+    | isConson c = 'E':'s':sonx (c:cs)     | otherwise  = 'e':'z':sonx (c:cs) sonx ('é':'s':c:cs)-    | c == 's'   = 'é':'s':sonx cs-    | isConson c = 'é':'s':sonx (c:cs)-    | otherwise  = 'é':'z':sonx (c:cs)-sonx ('e':'t':'t':cs) = 'é':'t':sonx cs-sonx "et" = "é"+    | c == 's'   = 'E':'s':sonx cs+    | isConson c = 'E':'s':sonx (c:cs)+    | otherwise  = 'E':'z':sonx (c:cs)+sonx ('e':'t':'t':cs) = 'E':'t':sonx cs+sonx "et" = "E" sonx ('e':'t':cs) = 'e':'t':sonx cs sonx ('e':'u':'n':c:cs)     | isVowel c = 'e':'n':sonx (c:cs)@@ -217,23 +223,30 @@ sonx "eux" = "e" sonx ('e':'u':'x':'i':cs) = 'e':'z':sonx ('i':cs) sonx ('e':'u':cs) = 'e':sonx cs-sonx "ex" = "éks"+sonx "ex" = "Eks" sonx ('e':'y':c:cs)-    | isConson c = 'é':sonx (c:cs)-    | otherwise  = 'é':sonx ('y':c:cs)-sonx "ez" = "é"+    | isConson c = 'E':sonx (c:cs)+    | otherwise  = 'E':sonx ('y':c:cs)+sonx "ez" = "E" -sonx ('è':cs) = 'é':sonx cs-sonx ('ê':cs) = 'é':sonx cs-sonx ('ë':'l':cs) = 'é':sonx ('l':cs)+sonx ('è':cs) = 'E':sonx cs+sonx ('ê':c:cs)+    | c == 't'  = 'E':sonx ('t':cs)+    | otherwise = 'E':sonx(c:cs)+sonx ('ë':'l':cs) = 'E':sonx ('l':cs)+sonx "é" = "E"+sonx ('é':c:cs)+    | c == 't'  = 'E':'t':sonx cs+    | otherwise = 'E':sonx(c:cs) + -- Starting with 'f' sonx ('f':'f':cs) = 'f':sonx cs  -- Starting with 'g' sonx "g" = "" sonx ('g':'e':cs) = 'j':sonx ('e':cs)-sonx ('g':'é':cs) = 'j':sonx ('é':cs)+sonx ('g':'é':cs) = 'j':sonx ('E':cs) sonx ('g':'i':cs) = 'j':sonx ('i':cs) sonx ('g':'n':cs) = 'n':sonx cs sonx ('g':'y':cs) = 'j':sonx ('y':cs)@@ -247,13 +260,14 @@ -- Starting with 'i' sonx "ic" = "ik" sonx "ics" = "ik"-sonx ('i':'e':'n':'n':cs) = 'i':'é':'n':sonx cs+sonx ('i':'e':'n':'n':cs) = 'i':'E':'n':sonx cs sonx ('i':'e':'n':cs) = 'i':'1':sonx cs sonx "in" = "1" sonx ('i':'n':c:cs)     | c == 'n'  = 'i':'n':sonx cs     | isVowel c = 'i':'n':sonx (c:cs)     | otherwise = '1':sonx (c:cs)+sonx "issent" = "is" sonx ('i':'s':c:cs)     | c == 's'   = 'i':'s':sonx cs     | isConson c = 'i':'s':sonx (c:cs)@@ -287,6 +301,7 @@     | otherwise = '3':sonx (c:cs) sonx ('o':'n':'n':cs) = 'o':'n':sonx cs sonx ('o':'n':cs) = '3':sonx cs+sonx "ossent" = "os" sonx ('o':'s':c:cs)     | c == 's'   = 'o':'s':sonx cs     | isConson c = 'o':'s':sonx (c:cs)@@ -302,7 +317,7 @@ sonx "p" = "" sonx ('p':'h':cs) = 'f':sonx cs sonx ('p':'p':cs) = 'p':sonx cs-sonx ('p':'a':'y':'s':cs) = 'p':'é':sonx ('i':'s':cs)+sonx ('p':'a':'y':'s':cs) = 'p':'E':sonx ('i':'s':cs)  -- Starting with 'q' sonx ('q':'u':'r':cs) = 'k':'u':sonx ('r':cs)@@ -315,15 +330,19 @@ -- Starting with 's' sonx "s" = "" sonx ('s':'s':cs) = 's':sonx cs+sonx ('s':'t':cs) = 's':'t':sonx cs sonx ('s':'c':'i':cs) = 's':sonx ('i':cs)  -- Starting with 't' sonx "t" = ""+sonx ('t':'i':'e':'r':cs) = 't':sonx ('i':'e':'r':cs)+sonx ('t':'i':cs) = 's':sonx ('i':cs) sonx ('t':'t':cs) = 't':sonx cs  -- Starting with 'u' sonx "un" = "1" sonx ('û':cs) = 'u':sonx cs+sonx "ussent" = "us" sonx ('u':'s':c:cs)     | c == 's'   = 'u':'s':sonx cs     | isConson c = 'u':'s':sonx (c:cs)@@ -359,7 +378,24 @@ -- -- prop> length (sonnex w) <= length w sonnex :: String -> String-sonnex = sonx . (map toLower)+sonnex = sonnex' . map toLower+    where sonnex' "cerf" = "sEr"+          sonnex' "cerfs" = "sEr"+          sonnex' "de"  = "de"+          sonnex' "est" = "E"+          sonnex' "es"  = "E"+          sonnex' "huit" = "uit"+          sonnex' "les" = "lE"+          sonnex' "mer" = "mEr"+          sonnex' "mes" = "mE"+          sonnex' "ressent" = "res2"+          sonnex' "serf" = "sEr"+          sonnex' "serfs" = "sEr"+          sonnex' ('s':'e':'p':'t':cs) = 's':'E':'t':sonx cs+          sonnex' "ses" = "sE"+          sonnex' "tes" = "tE"+          sonnex' ('t':'i':'e':'n':cs) = 't':sonx ('i':'e':'n':cs)+          sonnex' word = sonx word  -- | Compute a Sonnex code for a french phrase. --@@ -367,5 +403,5 @@ -- Since it uses the words/unwords couple, superfluous space character -- are removed. sonnexPhrase :: String -> String-sonnexPhrase phrase = unwords $ map sonnex (words phrase)+sonnexPhrase = unwords . map sonnex . words 
+ test/test-sonnex.hs view
@@ -0,0 +1,122 @@+{-# LANGUAGE TemplateHaskell #-}+{-|+Module      : TestSonnex+Description : Tests for HaMinitel+Copyright   : (c) Frédéric BISSON, 2014+License     : GPL-3+Maintainer  : zigazou@free.fr+Stability   : alpha+Portability : POSIX++Tests for Sonnex+-}++module Main where++import           Control.Monad       (unless)+import           System.Exit         (exitFailure)++import           Test.QuickCheck+import           Test.QuickCheck.All (quickCheckAll)++import           Text.Sonnex++allTheSame :: (Eq a) => [a] -> Bool+allTheSame xs = all (== head xs) (tail xs)++homonymsList :: [[String]]+homonymsList =+    [ [ "amande", "amende"]+    , [ "ancre", "encre" ]+    , [ "autel", "hôtel" ]+    , [ "balade", "ballade" ]+    , [ "basilic", "basilique"]+    , [ "boulot", "bouleau" ]+    , [ "cane", "canne" ]+    , [ "censé", "sensé" ]+    , [ "compte", "comte", "conte" ]+    , [ "cygne", "signe" ]+    , [ "date", "datte" ]+    , [ "dessin", "dessein" ]+    , [ "différend", "différent"]+    , [ "du", "dû" ]+    , [ "filtre", "philtre" ]+    , [ "flan", "flanc" ]+    , [ "foi", "foie", "fois" ]+    , [ "gène", "gêne" ]+    , [ "golf", "golfe" ]+    , [ "héraut", "héro", "héros" ]+    , [ "lacer", "lasser" ]+    , [ "lire", "lyre" ]+    , [ "maire", "mer", "mère" ]+    , [ "mal","mâle", "malle" ]+    , [ "mite", "mythe" ]+    , [ "pain", "pin" ]+    , [ "palais", "palet" ]+    , [ "a", "à" ]+    , [ "au", "aux", "haut" ]+    , [ "cerf", "serf", "serre" ]+    , [ "choeur", "chœur", "cœur", "coeur" ]+    , [ "cahos", "chaos" ]+    , [ "ce", "se" ]+    , [ "ai", "es", "est", "et" ]+    , [ "cric", "crique" ]+    , [ "on", "ont" ]+    , [ "champ", "chant" ]+    , [ "ou", "où" ]+    --, [ "c'est", "s'est", "ces", "ses", "sais", "sait" ]+    , [ "col", "colle" ]+    --, [ "mes", "mais", "m'est", "mets", "met" ]+    , [ "colon", "côlon" ]+    , [ "son", "sont", "sons" ]+    --, [ "court", "cours", "courent", "cour", "courre" ]+    , [ "ta", "t'a", "tas" ]+    , [ "dans", "d'en", "dent" ]+    , [ "ma", "m'a", "m'as", "mas", "mât" ]+    , [ "mon", "m'ont", "mont" ]+    , [ "la", "l'a", "l'as", "là" ]+    , [ "au", "aux", "haut" ]+    , [ "leur", "leurs", "l'heure", "leurre" ]+    , [ "sa", "ça", "çà" ]+    --, [ "les", "l'ai", "l'es", "l'est", "laid", "lait", "laie" ]+    , [ "peu", "peut", "peux" ]+    , [ "quand", "quant", "qu'en" ]+    , [ "ni", "n'y", "nie", "nies", "nid", "nids" ]+    , [ "ton", "t'ont", "thon" ]+    , [ "sans", "s'en", "sang", "cent" ]+    , [ "tant", "temps", "tend", "tends", "t'en" ]+    , [ "sois", "soit", "soient", "soie" ]+    , [ "quelque", "quelques" ]+    , [ "mur", "mûr", "mûre", "mure" ]+    , [ "dis", "dit", "dix" ]+    --, [ "quel", "quels", "quelle", "quelles", "qu'elle", "qu'elles" ]+    , [ "tous", "tout", "toux" ]+    , [ "si", "s'y", "scie" ]+    ]++prop_homonyms = forAll (elements homonymsList) $ \homonyms ->+    allTheSame (map sonnex homonyms)++tests :: [(String, String)]+tests =+    [ ("sept", "sEt")+    , ("septième", "sEtiEm")+    , ("huit", "uit")+    , ("potion", "posi3")+    , ("constitution", "k3stitusi3")+    , ("chrétien", "krEti1")+    , ("châtier", "CatiE")+    , ("tienne", "tiEn")+    , ("manger", "m2jE")+    , ("siffler", "siflE")+    , ("passionnant", "pasion2")+    ]++prop_tests = forAll (elements tests) $ \(source, result) ->+    sonnex source == result++return []++main = do+    allPass <- $quickCheckAll+    unless allPass exitFailure