phonetic-languages-phonetics-basics 0.2.2.0 → 0.3.0.0
raw patch · 5 files changed
+188/−7 lines, 5 filesdep +mmsyn2-arraydep +mmsyn5PVP ok
version bump matches the API change (PVP)
Dependencies added: mmsyn2-array, mmsyn5
API changes (from Hackage documentation)
+ Data.Phonetic.Languages.Syllables: P :: !Int8 -> PhoneticType
+ Data.Phonetic.Languages.Syllables: PF :: (SegmentationInfo1 -> [PRS] -> Bool) -> SegmentationPredFunction
+ Data.Phonetic.Languages.Syllables: SI :: !Int8 -> Int8 -> SegmentationInfo1
+ Data.Phonetic.Languages.Syllables: SP1 :: SegmentationInfo1 -> [SegmentationPredFunction] -> [([PRS] -> [PRS], [PRS] -> [PRS])] -> SegmentationRules1
+ Data.Phonetic.Languages.Syllables: SylS :: !Char -> !PhoneticType -> PRS
+ Data.Phonetic.Languages.Syllables: [charS] :: PRS -> !Char
+ Data.Phonetic.Languages.Syllables: [fieldN] :: SegmentationInfo1 -> !Int8
+ Data.Phonetic.Languages.Syllables: [infoS] :: SegmentationRules1 -> SegmentationInfo1
+ Data.Phonetic.Languages.Syllables: [pF] :: SegmentationRules1 -> [SegmentationPredFunction]
+ Data.Phonetic.Languages.Syllables: [phoneType] :: PRS -> !PhoneticType
+ Data.Phonetic.Languages.Syllables: [predicateN] :: SegmentationInfo1 -> Int8
+ Data.Phonetic.Languages.Syllables: [res] :: SegmentationRules1 -> [([PRS] -> [PRS], [PRS] -> [PRS])]
+ Data.Phonetic.Languages.Syllables: createSyllablesPL :: GWritingSystemPRPLX -> [(Char, Char)] -> CharPhoneticClassification -> SegmentPredicates -> String -> String -> String -> [[[PRS]]]
+ Data.Phonetic.Languages.Syllables: data PRS
+ Data.Phonetic.Languages.Syllables: data PhoneticType
+ Data.Phonetic.Languages.Syllables: data SegmentationInfo1
+ Data.Phonetic.Languages.Syllables: data SegmentationPredFunction
+ Data.Phonetic.Languages.Syllables: data SegmentationRules1
+ Data.Phonetic.Languages.Syllables: divCnsnts :: [(Char, Char)] -> SegmentPredicates -> [PRS] -> ([PRS] -> [PRS], [PRS] -> [PRS])
+ Data.Phonetic.Languages.Syllables: divVwls :: [[PRS]] -> [[PRS]]
+ Data.Phonetic.Languages.Syllables: groupSnds :: [PRS] -> [[PRS]]
+ Data.Phonetic.Languages.Syllables: instance GHC.Classes.Eq Data.Phonetic.Languages.Syllables.PRS
+ Data.Phonetic.Languages.Syllables: instance GHC.Classes.Eq Data.Phonetic.Languages.Syllables.PhoneticType
+ Data.Phonetic.Languages.Syllables: instance GHC.Classes.Eq Data.Phonetic.Languages.Syllables.SegmentationInfo1
+ Data.Phonetic.Languages.Syllables: instance GHC.Classes.Ord Data.Phonetic.Languages.Syllables.PRS
+ Data.Phonetic.Languages.Syllables: instance GHC.Classes.Ord Data.Phonetic.Languages.Syllables.PhoneticType
+ Data.Phonetic.Languages.Syllables: isNotVowel2 :: PRS -> PRS -> Bool
+ Data.Phonetic.Languages.Syllables: isSonorous1 :: PRS -> Bool
+ Data.Phonetic.Languages.Syllables: isVoicedC1 :: PRS -> Bool
+ Data.Phonetic.Languages.Syllables: isVoicelessC1 :: PRS -> Bool
+ Data.Phonetic.Languages.Syllables: isVowel1 :: PRS -> Bool
+ Data.Phonetic.Languages.Syllables: isVwl :: Char -> Bool
+ Data.Phonetic.Languages.Syllables: notEqC :: [(Char, Char)] -> PRS -> PRS -> Bool
+ Data.Phonetic.Languages.Syllables: reSyllableCntnts :: [(Char, Char)] -> SegmentPredicates -> [[PRS]] -> [[PRS]]
+ Data.Phonetic.Languages.Syllables: sndGroups :: [PRS] -> [[PRS]]
+ Data.Phonetic.Languages.Syllables: str2PRSs :: CharPhoneticClassification -> String -> StringRepresentation
+ Data.Phonetic.Languages.Syllables: type CharPhoneticClassification = [PRS]
+ Data.Phonetic.Languages.Syllables: type SegmentPredicates = [SegmentationRules1]
+ Data.Phonetic.Languages.Syllables: type StringRepresentation = [PRS]
Files
- ChangeLog.md +5/−0
- Data/Phonetic/Languages/Base.hs +7/−3
- Data/Phonetic/Languages/Syllables.hs +172/−0
- Data/Phonetic/Languages/Undefined.hs +1/−1
- phonetic-languages-phonetics-basics.cabal +3/−3
ChangeLog.md view
@@ -16,3 +16,8 @@ ## 0.2.2.0 -- 2021-04-20 * Second version revised B. Fixed issues with being not compiled because of no Ix instance specified for Array first argument. ++## 0.3.0.0 -- 2021-04-20++* Third version. Added a new module Data.Phonetic.Languages.Syllables for the general syllable segmentation. Added new+lightweight dependencies of mmsyn5 and mmsyn2-array.
Data/Phonetic/Languages/Base.hs view
@@ -176,7 +176,7 @@ {-# INLINE fHelp4 #-} -- | Partial equivalence that is used to find the appropriate 'PhoneticsRepresentationPL' for the class of--- 'PhoneticRepresentationPLX' values. +-- 'PhoneticsRepresentationPLX' values. (~=) :: PhoneticsRepresentationPL -> PhoneticsRepresentationPLX -> Bool (PR xs ys zs) ~= (PRC xs1 ys1 zs1 _) = xs == xs1 && ys == ys1 && zs == zs1 (PRAfter xs ys) ~= (PRAfterC xs1 ys1 _) = xs == xs1 && ys == ys1@@ -185,7 +185,7 @@ _ ~= _ = False -- | Partial equivalence that is used to find the appropriate 'PhoneticsRepresentationPL' for the class of--- 'PhoneticRepresentationPLX' values. +-- 'PhoneticsRepresentationPLX' values. compareG :: PhoneticsRepresentationPL -> PhoneticsRepresentationPLX -> Ordering compareG (PR xs ys zs) (PRC xs1 ys1 zs1 _) | xs /= xs1 = compare xs xs1@@ -239,7 +239,7 @@ !k = unsafeAt arr (I# i#) !m = unsafeAt arr (I# i#) -{-| The following is taken from the 'Data.Either' module from @base@ package.+{- The following CPP macros contents is taken from the 'Data.Either' module from @base@ package. -} #ifdef __GLASGOW_HASKELL__ #if __GLASGOW_HASKELL__<802@@ -253,6 +253,10 @@ #endif #endif +{-| Finds and element in the 'Array' that the corresponding 'PhoneticsRepresentationPLX' from the first argument is '~=' to the+it. The 'String' arguments inside the tuple pair are the 'beforeString' and the 'afterString' elements of it to be used in 'Right'+case.+-} findSAI :: PhoneticRepresentationXInter -> (String, String)
+ Data/Phonetic/Languages/Syllables.hs view
@@ -0,0 +1,172 @@+{-# OPTIONS_HADDOCK show-extensions #-}+{-# OPTIONS_GHC -funbox-strict-fields #-}+{-# LANGUAGE BangPatterns #-}++-- |+-- Module : Data.Phonetic.Languages.Syllables+-- Copyright : (c) OleksandrZhabenko 2020-2021+-- License : MIT+-- Stability : Experimental+-- Maintainer : olexandr543@yahoo.com+--+-- This module works with syllable segmentation. The generalized version for the module+-- 'Languages.Phonetic.Ukrainian.Syllable.Arr' from @ukrainian-phonetics-basic-array@ package.+-- ++module Data.Phonetic.Languages.Syllables where++import Prelude hiding (mappend)+import Data.Monoid+import Data.Typeable+import qualified Data.List as L (groupBy,find,findIndex)+import Data.Phonetic.Languages.Base+import CaseBi.Arr+import Data.List.InnToOut.Basic (mapI)+import Data.Maybe (mapMaybe,fromJust)+import GHC.Int++-- Inspired by: https://github.com/OleksandrZhabenko/mm1/releases/tag/0.2.0.0++-- CAUTION: Please, do not mix with the show7s functions, they are not interoperable.++data PRS = SylS {+ charS :: !Char, -- ^ Phonetic languages phenomenon representation. Usually, a phoneme, but it can be otherwise something different.+ phoneType :: !PhoneticType -- ^ Some encoded type.+} deriving ( Eq, Typeable )++instance Ord PRS where+ compare (SylS x1 y1) (SylS x2 y2) =+ case compare x1 x2 of+ EQ -> compare y1 y2+ ~z -> z++data PhoneticType = P !Int8 deriving (Eq, Ord)++{-| The list must be sorted in the ascending order to be used in the module correctly.+-}+type CharPhoneticClassification = [PRS]++{-| The 'String' of converted phonetic language representation 'Char' data is converted to this type to apply syllable+segmentation or other transformations.+-}+type StringRepresentation = [PRS]++str2PRSs :: CharPhoneticClassification -> String -> StringRepresentation+str2PRSs zs = map (\c -> fromJust . L.find ((== c) . charS) $ zs)+ +-- | Function-predicate 'isVowel1' checks whether its argument is a vowel representation in the 'PRS' format.+isVowel1 :: PRS -> Bool+isVowel1 = (== P 0) . phoneType+{-# INLINE isVowel1 #-}++-- | Function-predicate 'isVwl' checks whether its argument is a vowel representation in the 'Char' format.+isVwl :: Char -> Bool+isVwl = getBFstLSorted' False [('a',True),('e',True),('i',True),('o',True),('u',True),('y',True)]+{-# INLINE isVwl #-}++-- | Function-predicate 'isSonorous1' checks whether its argument is a sonorous consonant representation in the 'PRS' format.+isSonorous1 :: PRS -> Bool+isSonorous1 = (`elem` [P 1,P 2]) . phoneType+{-# INLINE isSonorous1 #-}++-- | Function-predicate 'isVoicedC1' checks whether its argument is a voiced consonant representation in the 'PRS' format.+isVoicedC1 :: PRS -> Bool+isVoicedC1 = (`elem` [P 3,P 4]) . phoneType+{-# INLINE isVoicedC1 #-}++-- | Function-predicate 'isVoiceless1' checks whether its argument is a voiceless consonant representation in the 'PRS' format.+isVoicelessC1 :: PRS -> Bool+isVoicelessC1 = (`elem` [P 5,P 6]) . phoneType+{-# INLINE isVoicelessC1 #-}++-- | Binary function-predicate 'isNotVowel2' checks whether its arguments are both consonant representations in the 'PRS' format.+isNotVowel2 :: PRS -> PRS -> Bool+isNotVowel2 x y+ | phoneType x == P 0 || phoneType y == P 0 = False+ | otherwise = True+{-# INLINE isNotVowel2 #-}++-- | Binary function-predicate 'notEqC' checks whether its arguments are not the same consonant sound representations (not taking palatalization into account).+notEqC+ :: [(Char,Char)] -- ^ The pairs of the 'Char' that corresponds to the similar phonetic languages consonant phenomenon (e. g. allophones). Must be sorted in the ascending order to be used correctly. + -> PRS+ -> PRS+ -> Bool+notEqC xs x y+ | (== cy) . getBFstLSorted' cx xs $ cx = False+ | otherwise = cx /= cy+ where !cx = charS x+ !cy = charS y++-- | Function 'sndGroups' converts a word being a list of 'PRS' to the list of phonetically similar (consonants grouped with consonants and each vowel separately)+-- sounds representations in 'PRS' format.+sndGroups :: [PRS] -> [[PRS]]+sndGroups ys@(_:_) = L.groupBy isNotVowel2 ys+sndGroups _ = []++groupSnds :: [PRS] -> [[PRS]]+groupSnds = L.groupBy (\x y -> ((== P 0) . phoneType $ x) == ((== P 0) . phoneType $ y))++data SegmentationInfo1 = SI {+ fieldN :: !Int8, -- ^ Number of fields in the pattern matching that are needed to apply the segmentation rules. Not less than 1.+ predicateN :: Int8 -- ^ Number of predicates in the definition for the 'fieldN' that are needed to apply the segmentation rules.+} deriving (Eq)++data SegmentationPredFunction = PF (SegmentationInfo1 -> [PRS] -> Bool)++data SegmentationRules1 = SP1 {+ infoS :: SegmentationInfo1, + pF :: [SegmentationPredFunction], -- ^ The list must be sorted in the appropriate order of the guards usage for the predicates.+ -- The length of the list must be equal to the ('fromEnum' . 'predicateN' . 'infoS') value.+ res :: [([PRS] -> [PRS],[PRS] -> [PRS])] -- ^ The corresponding list of rules for segmentation.+} ++{-| List of the 'SegmentationRules1' sorted in the descending order by the 'fieldN' 'SegmentationInfo1' data and where the+length of all the 'SegmentationPredFunction' lists of 'PRS' are equal to the 'fieldN' 'SegmentationInfo1' data by definition.+-}+type SegmentPredicates = [SegmentationRules1]++-- | Function 'divCnsnts' is used to divide groups of consonants into two-elements lists that later are made belonging to+-- different neighbour syllables if the group is between two vowels in a word. The group must be not empty, but this is not checked.+-- The example phonetical information for the proper performance in Ukrainian can be found from the:+-- https://msn.khnu.km.ua/pluginfile.php/302375/mod_resource/content/1/%D0%9B.3.%D0%86%D0%86.%20%D0%A1%D0%BA%D0%BB%D0%B0%D0%B4.%D0%9D%D0%B0%D0%B3%D0%BE%D0%BB%D0%BE%D1%81.pdf+-- The example of the 'divCnsnts' can be found at: https://hackage.haskell.org/package/ukrainian-phonetics-basic-array-0.1.2.0/docs/src/Languages.Phonetic.Ukrainian.Syllable.Arr.html#divCnsnts+divCnsnts :: [(Char,Char)] -> SegmentPredicates -> [PRS] -> ([PRS] -> [PRS],[PRS] -> [PRS])+divCnsnts ks gs xs@(_:_) = res js !! ix+ where !l = length xs+ !js = fromJust . L.find ((== l) . fromEnum . fieldN . infoS) $ gs -- js :: SegmentationRules1+ !ix = fromJust . L.findIndex (\(PF f) -> f (infoS js) xs) . pF $ js+divCnsnts _ _ [] = (id,id)++reSyllableCntnts :: [(Char,Char)] -> SegmentPredicates -> [[PRS]] -> [[PRS]]+reSyllableCntnts ks gs (xs:ys:zs:xss)+ | (/= P 0) . phoneType . last $ ys = fst (divCnsnts ks gs ys) xs:reSyllableCntnts ks gs (snd (divCnsnts ks gs ys) zs:xss)+ | otherwise = reSyllableCntnts ks gs ((xs `mappend` ys):zs:xss)+reSyllableCntnts _ _ (xs:ys:_) = [(xs `mappend` ys)]+reSyllableCntnts _ _ xss = xss++divVwls :: [[PRS]] -> [[PRS]]+divVwls = mapI (\ws -> (length . filter ((== P 0) . phoneType) $ ws) > 1) h3+ where h3 us = [ys `mappend` take 1 zs] `mappend` (L.groupBy (\x y -> phoneType x == P 0 && phoneType y /= P 0) . drop 1 $ zs)+ where (ys,zs) = span (\t -> phoneType t /= P 0) us++createSyllablesPL+ :: GWritingSystemPRPLX+ -> [(Char,Char)]+ -> CharPhoneticClassification+ -> SegmentPredicates+ -> String -- ^ Corresponds to the \'0\' symbol delimiter in the @ukrainian-phonetics-basic-array@ package.+ -> String -- ^ Corresponds to the \'1\' and \'-\' symbol delimiters in the @ukrainian-phonetics-basic-array@ package.+ -> String -- ^ Actually the converted 'String'.+ -> [[[PRS]]]+createSyllablesPL wrs ks cs gs us vs = map (divVwls . reSyllableCntnts ks gs . groupSnds . str2PRSs cs) . words1 . mapMaybe g . convertToProperPL . map (\x -> if x == '-' then ' ' else x)+ where g x+ | x `elem` us = Nothing+ | x `notElem` vs = Just x+ | otherwise = Just ' '+ words1 xs = if null ts then [] else w : words1 s'' -- Practically this is an optimized version for this case 'words' function from Prelude.+ where ts = dropWhile (== ' ') xs+ (w, s'') = span (/= ' ') ts+ {-# NOINLINE words1 #-}+ convertToProperPL = map char . stringToXG wrs+{-# INLINE createSyllablesPL #-}
Data/Phonetic/Languages/Undefined.hs view
@@ -80,7 +80,7 @@ implementation has the same name and signature as here and the data type is used there. Please, use this function only as a type and semantics template and implement your own one where needed. After you have defined the 'rules' and 'showRepr' functions, you can implement the instance for 'Show' class-for the 'PhoneticRepresentationPL' as:+for the 'PhoneticsRepresentationPL' as: instance Show PhoneticsRepresentationPL where show = showRepr . rulesPR {-# INLINE show #-}
phonetic-languages-phonetics-basics.cabal view
@@ -3,7 +3,7 @@ -- http://haskell.org/cabal/users-guide/ name: phonetic-languages-phonetics-basics-version: 0.2.2.0+version: 0.3.0.0 synopsis: A library for working with generalized phonetic languages usage. description: There already exists a Ukrainian implementation for the phonetic languages approach published at: https://hackage.haskell.org/package/phonetic-languages-simplified-examples-array. It is optimized for the Ukrainian only and needs to be rewritten for every new language mostly from scratch using it as a template. To avoid this boilerplate, this one is provided. It can be used for different languages and even for music or other fields. homepage: https://hackage.haskell.org/package/phonetic-languages-phonetics-basics@@ -18,10 +18,10 @@ cabal-version: >=1.10 library- exposed-modules: Data.Phonetic.Languages.Undefined, Data.Phonetic.Languages.Base+ exposed-modules: Data.Phonetic.Languages.Undefined, Data.Phonetic.Languages.Base, Data.Phonetic.Languages.Syllables -- other-modules: other-extensions: CPP, BangPatterns, UnboxedTuples, MagicHash ghc-options: -funbox-strict-fields- build-depends: base >=4.8 && <4.15+ build-depends: base >=4.8 && <4.15, mmsyn2-array >= 0.1.3 && <1, mmsyn5 >= 0.5 && <1 -- hs-source-dirs: default-language: Haskell2010