packages feed

polimorf 0.5.0 → 0.6.0

raw patch · 2 files changed

+147/−125 lines, 2 filesdep +text-binarydep ~dawgPVP ok

version bump matches the API change (PVP)

Dependencies added: text-binary

Dependency ranges changed: dawg

API changes (from Hackage documentation)

- Data.PoliMorf: ByBase :: RelCode
- Data.PoliMorf: ByForm :: RelCode
- Data.PoliMorf: Exact :: RelCode
- Data.PoliMorf: data RelCode
- Data.PoliMorf: instance Binary RelCode
- Data.PoliMorf: instance Eq RelCode
- Data.PoliMorf: instance Ord RelCode
- Data.PoliMorf: instance Read RelCode
- Data.PoliMorf: instance Show RelCode
- Data.PoliMorf: merge :: Ord a => BaseMap -> DAWG (Set a) -> DAWG (Map a RelCode)
- Data.PoliMorf: mergeWith :: Ord a => (String -> String -> a -> a) -> BaseMap -> DAWG (Set a) -> DAWG (Map a RelCode)
- Data.PoliMorf: toBase :: Entry -> Maybe Rule
+ Data.PoliMorf: anaWord :: AnaMap -> Form -> Map Base (Set Tag)
+ Data.PoliMorf: instance Binary Rule
+ Data.PoliMorf: mkAnaMap :: [Entry] -> AnaMap
+ Data.PoliMorf: type AnaMap = DAWG (Map Rule (Set Tag))
+ Data.PoliMorf: type DAWG a = DAWG Trans Char () a

Files

Data/PoliMorf.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE PatternGuards #-} {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE RecordWildCards #-}  -- | The module provides functionality for manipulating PoliMorf, the -- morphological dictionary for Polish. Apart from IO utilities there@@ -21,32 +22,37 @@ , readPoliMorf , parsePoliMorf --- * Merging+-- * Utilities , Rule (..) , apply-, toBase+, DAWG+, AnaMap+, mkAnaMap+, anaWord , mkRuleMap , BaseMap , mkBaseMap , FormMap , mkFormMap-, RelCode (..)-, mergeWith-, merge++-- -- * Merging+-- , RelCode (..)+-- , mergeWith+-- , merge ) where  import Control.Applicative ((<$>), (<*>))-import Data.Maybe (catMaybes)-import Data.Monoid (mappend)+-- import Data.Maybe (catMaybes)+-- import Data.Monoid (mappend) import Data.Binary (Binary, get, put)+import Data.Text.Binary () import qualified Data.Set as S import qualified Data.Map as M import qualified Data.Text as T import qualified Data.Text.Lazy as L import qualified Data.Text.Lazy.IO as L-import qualified Data.DAWG as D--import Debug.Trace (trace)+import qualified Data.DAWG.Static as D+import qualified Data.DAWG.Trans.Vector as D  -- | A form. type Form = T.Text@@ -99,23 +105,14 @@     , suffix    :: !T.Text }     deriving (Show, Eq, Ord) +instance Binary Rule where+    put Rule{..} = put cut >> put suffix+    get = Rule <$> get <*> get+ -- | Apply the rule. apply :: Rule -> T.Text -> T.Text apply r x = T.take (T.length x - cut r) x `T.append` suffix r --- | Determine the rule needed to translate the form into its base form.-toBase :: Entry -> Maybe Rule-toBase x-    | "sup" `T.isInfixOf` tag x && "naj" `T.isPrefixOf` form x = Nothing-    | "neg" `T.isInfixOf` tag x && "nie" `T.isPrefixOf` form x = Nothing-    | otherwise =-        let k = lcp (form x) (base x)-        in  Just $ Rule (T.length (form x) - k) (T.drop k (base x))-  where-    lcp a b = case T.commonPrefixes a b of-        Just (c, _, _)  -> T.length c-        Nothing         -> trace (show (form x, base x)) 0- -- | Make a rule to translate between two strings. between :: T.Text -> T.Text -> Rule between source dest =@@ -126,15 +123,39 @@         Just (c, _, _)  -> T.length c         Nothing         -> 0 +type DAWG a = D.DAWG D.Trans Char () a++-- | A map from forms to their potential interpretations.  It can be used+-- directly to determine all potential dictionary interpretations of a+-- given form.+type AnaMap = DAWG (M.Map Rule (S.Set Tag))++-- | Construct an 'AnaMap' from a list of entries.+mkAnaMap :: [Entry] -> AnaMap+mkAnaMap xs = D.fromListWith (M.unionWith S.union) $+    [ ( T.unpack (form x)+      , M.singleton+            (between (form x) (base x))+            (S.singleton (tag x)) )+    | x <- xs ]++-- | Analyse word.+anaWord :: AnaMap -> Form -> M.Map Base (S.Set Tag)+anaWord anaMap x = case D.lookup (T.unpack x) anaMap of+    Just m  -> M.fromListWith S.union+        [ (apply rule x, tags)+        | (rule, tags) <- M.toList m ]+    Nothing -> M.empty+ -- | A map from forms to their possible base forms (there may be many since -- the form may be a member of multiple lexemes).-type BaseMap = D.DAWG (S.Set Rule)+type BaseMap = DAWG (S.Set Rule)  -- | A map from base forms to all their potential forms.-type FormMap = D.DAWG (S.Set Rule)+type FormMap = DAWG (S.Set Rule)  -- | Make a rule map from a list of entries.-mkRuleMap :: [(T.Text, T.Text)] -> D.DAWG (S.Set Rule)+mkRuleMap :: [(T.Text, T.Text)] -> DAWG (S.Set Rule) mkRuleMap xs = D.fromListWith S.union $     [ ( T.unpack x       , S.singleton (between x y) )@@ -148,100 +169,100 @@ mkFormMap :: [Entry] -> FormMap mkFormMap = mkRuleMap . map ((,) <$> base <*> form) --- | Reliability information: how did we assign a particular label to--- a particular word form.-data RelCode-    = ByForm    -- ^ Based on labels of other forms within the same lexeme-    | ByBase    -- ^ Label assigned based on a lemma label  -    | Exact     -- ^ Label assigned in a direct manner-    deriving (Eq, Ord, Show, Read)--instance Binary RelCode where-    put Exact   = put '1'-    put ByBase  = put '2'-    put ByForm  = put '3'-    get = get >>= \x -> return $ case x of-        '1' -> Exact-        '2' -> ByBase-        '3' -> ByForm-        c   -> error $ "get: invalid RelCode code '" ++ [c] ++ "'"---- | Merge the 'BaseMap' with the dictionary resource which maps forms to sets--- of labels.  Every label is assigned a 'RelCode' which tells what is the--- relation between the label and the form. It is a generalized version--- of the 'merge' function with additional function @f x y y'label@ which--- can be used to determine the resultant set of labels for the form @x@--- given ,,similar'' form @y@ and its original label @y'label@.--- There are three kinds of labels:--- 'Exact' labels assigned in a direct manner, 'ByBase' labels assigned--- to all forms which have a base form with a label in the input dictionary,--- and 'ByForm' labels assigned to all forms which have a related form from the--- same lexeme with a label in the input dictionary.-mergeWith-    :: Ord a-    => (String -> String -> a -> a)-    -> BaseMap-    -> D.DAWG (S.Set a)-    -> D.DAWG (M.Map a RelCode)-mergeWith f poli dict0 = D.fromList-    [ (x, combine x)-    | x <- keys ]-  where-    -- Keys in the output dictionary.-    keys = join (D.keys poli) (D.keys dict0)--    -- Combining function.-    combine x = (M.unionsWith max . catMaybes)-        [ label Exact  <$> D.lookup x dict0 -        , label ByBase <$> D.lookup x dict1-        , label ByForm <$> D.lookup x dict2 ]--    label :: Ord a => RelCode -> S.Set a -> M.Map a RelCode-    label code s = M.fromList [(x, code) | x <- S.toList s]--    -- Extended to all base forms of dict0 keys.-    dict1 = D.fromListWith mappend-        [ (lemma, f'Set lemma _form x)-        | (_form, x) <- D.assocs dict0-        , lemma <- elemsOn poli _form ]--    -- Extended to all forms of dict0 keys.-    dict2 = D.fromListWith mappend-        [ (form', f'Set form' _form x)-        | (_form, x) <- D.assocs dict0-        , lemma <- elemsOn poli _form-        , form' <- elemsOn ilop lemma ]--    -- Inverse poli dictionary.-    ilop = mkRuleMap-        [ (base'Text, form'Text)-        | (form'String, rules) <- D.assocs poli-        , rule <- S.toList rules-        , let form'Text = T.pack form'String-        , let base'Text = apply rule form'Text ]-    -    -- Merge to ascending lists.-    join (x:xs) (y:ys)-        | x < y     = x : join xs (y:ys)-        | x > y     = y : join (x:xs) ys-        | otherwise = x : join xs ys-    join xs []  = xs-    join [] ys  = ys--    -- Version of f function working on label sets.-    f'Set v w = S.fromList . map (f v w) . S.toList---- | A specialized version of the 'mergeWith' function which doesn't--- change labels in the resultant 'D.DAWG'.-merge-    :: Ord a => BaseMap-    -> D.DAWG (S.Set a)-    -> D.DAWG (M.Map a RelCode)-merge = mergeWith $ \_ _ x -> x--elemsOn :: D.DAWG (S.Set Rule) -> String -> [String]-elemsOn m x = case x `D.lookup` m of-    Just s  ->-        [ T.unpack . apply rule . T.pack $ x-        | rule <- S.toList s ]-    Nothing -> []+-- -- | Reliability information: how did we assign a particular label to+-- -- a particular word form.+-- data RelCode+--     = ByForm    -- ^ Based on labels of other forms within the same lexeme+--     | ByBase    -- ^ Label assigned based on a lemma label  +--     | Exact     -- ^ Label assigned in a direct manner+--     deriving (Eq, Ord, Show, Read)+-- +-- instance Binary RelCode where+--     put Exact   = put '1'+--     put ByBase  = put '2'+--     put ByForm  = put '3'+--     get = get >>= \x -> return $ case x of+--         '1' -> Exact+--         '2' -> ByBase+--         '3' -> ByForm+--         c   -> error $ "get: invalid RelCode code '" ++ [c] ++ "'"+-- +-- -- | Merge the 'BaseMap' with the dictionary resource which maps forms to sets+-- -- of labels.  Every label is assigned a 'RelCode' which tells what is the+-- -- relation between the label and the form. It is a generalized version+-- -- of the 'merge' function with additional function @f x y y'label@ which+-- -- can be used to determine the resultant set of labels for the form @x@+-- -- given ,,similar'' form @y@ and its original label @y'label@.+-- -- There are three kinds of labels:+-- -- 'Exact' labels assigned in a direct manner, 'ByBase' labels assigned+-- -- to all forms which have a base form with a label in the input dictionary,+-- -- and 'ByForm' labels assigned to all forms which have a related form from the+-- -- same lexeme with a label in the input dictionary.+-- mergeWith+--     :: Ord a+--     => (String -> String -> a -> a)+--     -> BaseMap+--     -> DAWG (S.Set a)+--     -> DAWG (M.Map a RelCode)+-- mergeWith f poli dict0 = D.fromList+--     [ (x, combine x)+--     | x <- keys ]+--   where+--     -- Keys in the output dictionary.+--     keys = join (D.keys poli) (D.keys dict0)+-- +--     -- Combining function.+--     combine x = (M.unionsWith max . catMaybes)+--         [ label Exact  <$> D.lookup x dict0 +--         , label ByBase <$> D.lookup x dict1+--         , label ByForm <$> D.lookup x dict2 ]+-- +--     label :: Ord a => RelCode -> S.Set a -> M.Map a RelCode+--     label code s = M.fromList [(x, code) | x <- S.toList s]+-- +--     -- Extended to all base forms of dict0 keys.+--     dict1 = D.fromListWith mappend+--         [ (lemma, f'Set lemma _form x)+--         | (_form, x) <- D.assocs dict0+--         , lemma <- elemsOn poli _form ]+-- +--     -- Extended to all forms of dict0 keys.+--     dict2 = D.fromListWith mappend+--         [ (form', f'Set form' _form x)+--         | (_form, x) <- D.assocs dict0+--         , lemma <- elemsOn poli _form+--         , form' <- elemsOn ilop lemma ]+-- +--     -- Inverse poli dictionary.+--     ilop = mkRuleMap+--         [ (base'Text, form'Text)+--         | (form'String, rules) <- D.assocs poli+--         , rule <- S.toList rules+--         , let form'Text = T.pack form'String+--         , let base'Text = apply rule form'Text ]+--     +--     -- Merge to ascending lists.+--     join (x:xs) (y:ys)+--         | x < y     = x : join xs (y:ys)+--         | x > y     = y : join (x:xs) ys+--         | otherwise = x : join xs ys+--     join xs []  = xs+--     join [] ys  = ys+-- +--     -- Version of f function working on label sets.+--     f'Set v w = S.fromList . map (f v w) . S.toList+-- +-- -- | A specialized version of the 'mergeWith' function which doesn't+-- -- change labels in the resultant 'DAWG'.+-- merge+--     :: Ord a => BaseMap+--     -> DAWG (S.Set a)+--     -> DAWG (M.Map a RelCode)+-- merge = mergeWith $ \_ _ x -> x+-- +-- elemsOn :: DAWG (S.Set Rule) -> String -> [String]+-- elemsOn m x = case x `D.lookup` m of+--     Just s  ->+--         [ T.unpack . apply rule . T.pack $ x+--         | rule <- S.toList s ]+--     Nothing -> []
polimorf.cabal view
@@ -1,5 +1,5 @@ name:               polimorf-version:            0.5.0+version:            0.6.0 synopsis:           Working with the PoliMorf dictionary description:     The library provides functionality for manipulating PoliMorf, the@@ -23,7 +23,8 @@       , containers       , text       , binary-      , dawg >= 0.5 && < 0.6+      , text-binary >= 0.1 && < 0.2+      , dawg >= 0.8 && < 0.9      exposed-modules:         Data.PoliMorf