packages feed

data-named 0.2.0 → 0.3.0

raw patch · 3 files changed

+103/−94 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.Named.Graph: disjointForest :: (Show k, Ord k) => (k -> Int) -> Graph k v -> Forest k
- Data.Named.Graph: instance Monad RanM
- Data.Named.Graph: node :: (Show k, Ord k) => Graph k v -> k -> v
- Data.Named.Graph: nodeMap :: Graph k v -> Map k v
- Data.Named.Tree: addWords :: Ord k => Forest k -> [k] -> Forest k
- Data.Named.Tree: instance Eq Span
- Data.Named.Tree: instance Ord Span
- Data.Named.Tree: instance Show Span
+ Data.Named.Graph: bounds :: Graph n w -> (w, w)
+ Data.Named.Graph: instance Monad (RanM w)
+ Data.Named.Graph: toForest :: (Ord n, Ix w) => Graph n w -> Forest (Either n w)
+ Data.Named.Tree: instance Eq w => Eq (Span w)
+ Data.Named.Tree: instance Ord w => Ord (Span w)
+ Data.Named.Tree: instance Show w => Show (Span w)
+ Data.Named.Tree: mapLeaves :: (a -> b) -> Tree (Either c a) -> Tree (Either c b)
+ Data.Named.Tree: mapNodes :: (a -> b) -> Tree (Either a c) -> Tree (Either b c)
- Data.Named.Graph: Graph :: Map k v -> Map k [k] -> Graph k v
+ Data.Named.Graph: Graph :: (w, w) -> Map n [Either n w] -> Graph n w
- Data.Named.Graph: data Graph k v
+ Data.Named.Graph: data Graph n w
- Data.Named.Graph: edgeMap :: Graph k v -> Map k [k]
+ Data.Named.Graph: edgeMap :: Graph n w -> Map n [Either n w]
- Data.Named.Graph: edges :: (Show k, Ord k) => Graph k v -> k -> [k]
+ Data.Named.Graph: edges :: Ord n => Graph n w -> n -> [Either n w]
- Data.Named.Graph: mkGraph :: Ord k => [(k, v, [k])] -> Graph k v
+ Data.Named.Graph: mkGraph :: (Ord n, Ix w) => (w, w) -> [(n, [Either n w])] -> Graph n w
- Data.Named.Graph: roots :: Ord k => Graph k v -> [k]
+ Data.Named.Graph: roots :: Ord n => Graph n w -> [n]
- Data.Named.Tree: (<>) :: Span -> Span -> Span
+ Data.Named.Tree: (<>) :: Ord w => Span w -> Span w -> Span w
- Data.Named.Tree: Span :: Int -> Int -> Span
+ Data.Named.Tree: Span :: w -> w -> Span w
- Data.Named.Tree: beg :: Span -> Int
+ Data.Named.Tree: beg :: Span w -> w
- Data.Named.Tree: data Span
+ Data.Named.Tree: data Span w
- Data.Named.Tree: end :: Span -> Int
+ Data.Named.Tree: end :: Span w -> w
- Data.Named.Tree: leafSpan :: Int -> Span
+ Data.Named.Tree: leafSpan :: w -> Span w
- Data.Named.Tree: sortForest :: Forest (k, Span) -> Forest (k, Span)
+ Data.Named.Tree: sortForest :: Ord w => Forest (k, Span w) -> Forest (k, Span w)
- Data.Named.Tree: sortTree :: Tree (k, Span) -> Tree (k, Span)
+ Data.Named.Tree: sortTree :: Ord w => Tree (k, Span w) -> Tree (k, Span w)
- Data.Named.Tree: span :: Tree (a, Span) -> Span
+ Data.Named.Tree: span :: Tree (a, Span w) -> Span w
- Data.Named.Tree: spanForest :: (k -> Int) -> Forest k -> Forest (k, Span)
+ Data.Named.Tree: spanForest :: Ord w => Forest (Either n w) -> Forest (Either n w, Span w)
- Data.Named.Tree: spanSet :: Span -> IntSet
+ Data.Named.Tree: spanSet :: Ix w => Span w -> Set w
- Data.Named.Tree: spanTree :: (k -> Int) -> Tree k -> Tree (k, Span)
+ Data.Named.Tree: spanTree :: Ord w => Tree (Either n w) -> Tree (Either n w, Span w)
- Data.Named.Tree: unSpanForest :: Forest (k, Span) -> Forest k
+ Data.Named.Tree: unSpanForest :: Forest (k, Span w) -> Forest k
- Data.Named.Tree: unSpanTree :: Tree (k, Span) -> Tree k
+ Data.Named.Tree: unSpanTree :: Tree (k, Span w) -> Tree k

Files

Data/Named/Graph.hs view
@@ -1,77 +1,105 @@ {-# LANGUAGE DoAndIfThenElse #-} --- | Implementation of a graph with each node identified by a unique key.--- It is a provisional module and it might be replaced by the standard--- graph from containers package in the future.+-- | Implementation of a graph with each internal node identified by a+-- unique key and each leaf represented by a position in the sentence.  module Data.Named.Graph ( Graph (..) , mkGraph-, node , edges , roots-, disjointForest+, toForest ) where +import Prelude hiding (span)+import Data.Either (lefts, rights)+import Data.Ix (Ix, range, inRange) import qualified Data.Set as S import qualified Data.Map as M import qualified Data.Tree as T  import Data.Named.Tree --- | A graph.-data Graph k v = Graph-    { nodeMap :: M.Map k v-    , edgeMap :: M.Map k [k] }+-- | A graph over a sentence.+data Graph n w = Graph+    { bounds  :: (w, w)+    , edgeMap :: M.Map n [Either n w] } --- | Make a graph from a list of (key, value, [children keys]) tuples.-mkGraph :: Ord k => [(k, v, [k])] -> Graph k v-mkGraph xs = -    Graph ns es+-- | Make a graph given the bounds and list of edges.+mkGraph :: (Ord n, Ix w) => (w, w) -> [(n, [Either n w])] -> Graph n w+mkGraph bs =+    Graph bs . M.fromList . map check   where-    ns = M.fromList [(k, v)  | (k, v, _)  <- xs]-    es = M.fromList [(k, ks) | (k, _, ks) <- xs]---- | Get node with the given key.-node :: (Show k, Ord k) => Graph k v -> k -> v-node g k = case M.lookup k (nodeMap g) of-    Nothing -> error $ "node: key " ++ show k ++ " not in the nodes map"-    Just v  -> v-{-# INLINE node #-}+    check (k, ks)+        | null ks =+            error "mkGraph: Left, internal node without output edges"+        | any (not . inRange bs) (rights ks) =+            error "mkGraph: Right, leaf node outside of bounds"+        | otherwise = (k, ks)  -- | Get keys of adjacent nodes for the given node key.-edges :: (Show k, Ord k) => Graph k v -> k -> [k]+edges :: Ord n => Graph n w -> n -> [Either n w] edges g k = case M.lookup k (edgeMap g) of-    Nothing -> error $ "edges: key " ++ show k ++ " not in the edges map"+    Nothing -> error "edges: key not in the map"     Just v  -> v {-# INLINE edges #-}  -- | Return all graph roots (i.e. nodes with no parents).-roots :: Ord k => Graph k v -> [k]+roots :: Ord n => Graph n w -> [n] roots g =-    let desc = S.fromList . concat . M.elems $ edgeMap g-    in  [k | (k, _) <- M.assocs (nodeMap g), not (k `S.member` desc)]+    let desc = S.fromList . lefts . concat . M.elems $ edgeMap g+    in  [k | k <- M.keys (edgeMap g), not (k `S.member` desc)] -generate :: (Show k, Ord k) => Graph k v -> k -> T.Tree k-generate g k  = T.Node k (map (generate g) (edges g k))+generate :: Ord n => Graph n w -> Either n w -> T.Tree (Either n w)+generate g (Left k) = T.Node (Left k) (map (generate g) (edges g k))+generate _ w        = T.Node w [] +prune :: Ord w => T.Forest (Either n w) -> T.Forest (Either n w)+prune = unSpanForest . run . chop . sortForest . spanForest++-- | Combine the disjoint forest with the list of words.+-- Discontinuities will be patched with no trace.+addWords :: Ix w => (w, w) -> T.Forest (Either n w) -> T.Forest (Either n w)+addWords (p, q) [] = [T.Node (Right x) [] | x <- range (p, q)]+addWords (p, q) ts+    = unSpanForest . T.subForest+    . sortTree . fillTree+    . dummyRoot+    . spanForest $ ts+  where+    dummyRoot = T.Node (undefined, Span p q)+    mkLeaf k  = T.Node (Right k, leafSpan k) []++    fillForest = map fillTree+    fillTree (T.Node n []) = T.Node n []+    fillTree (T.Node (k, s) us) =+        let m = spanSet s S.\\ S.unions (map (spanSet . span) us)+        in  T.Node (k, s) (fillForest us ++ map mkLeaf (S.toList m))++-- | Transform graph into a disjoint forest, i.e. with no mutually+-- overlapping trees.+toForest :: (Ord n, Ix w) => Graph n w -> T.Forest (Either n w)+toForest g = addWords (bounds g) . prune . map (generate g . Left) . roots $ g+ -- | A stateful monad for forest pruning.-newtype RanM a = RanM { runRanM :: Int -> (a, Int) }+newtype RanM w a = RanM { runRanM :: Maybe w -> (a, Maybe w) } -instance Monad RanM where+instance Monad (RanM w) where     return x     = RanM $ \s -> (x, s)     RanM v >>= f = RanM $ \s -> case v s of (x, s') -> runRanM (f x) s' -run :: RanM a -> a-run act = fst (runRanM act (-1))+run :: RanM w a -> a+run act = fst (runRanM act Nothing) -contains :: Int -> RanM Bool-contains k = RanM $ \m -> (k <= m, m)+contains :: Ord w => w -> RanM w Bool+contains k = RanM $ \m -> case m of+    Just x  -> (k <= x, m)+    Nothing -> (False,  m) -include :: Int -> RanM ()-include k = RanM $ \_ -> ((), k)+include :: w -> RanM w ()+include k = RanM $ \_ -> ((), Just k) -chop :: T.Forest (k, Span) -> RanM (T.Forest (k, Span))+chop :: Ord w => T.Forest (k, Span w) -> RanM w (T.Forest (k, Span w)) chop [] = return [] chop (T.Node (k, s) ts : us) = do     visited <- contains (end s)@@ -82,12 +110,3 @@         include (end s)         bs <- chop us         return (T.Node (k, s) as : bs)--prune :: (k -> Int) -> T.Forest k -> T.Forest k-prune f = unSpanForest . run . chop . sortForest . spanForest f---- | Spanning-like forest of a DAG.  Trees in the resulting forest are--- disjoint with respect to their ranges.  It is not checked if the input--- graph is actually a DAG.-disjointForest :: (Show k, Ord k) => (k -> Int) -> Graph k v -> T.Forest k-disjointForest f g = prune f . map (generate g) . roots $ g
Data/Named/Tree.hs view
@@ -2,11 +2,11 @@  module Data.Named.Tree ( --- * Combine with words-  addWords+-- -- * Combine with words+--   addWords  -- * Span-, Span (..)+  Span (..) , leafSpan , (<>) , spanSet@@ -21,90 +21,80 @@ , sortForest  -- * Utilities+, mapLeaves+, mapNodes , mapTrees ) where  import Prelude hiding (span) import Data.List (sortBy) import Data.Ord (comparing)+import Data.Ix (Ix, range) import qualified Data.Tree as T-import qualified Data.IntSet as S-import qualified Data.Map as M+import qualified Data.Set as S +-- | Map function over tree leaves.+mapLeaves :: (a -> b) -> T.Tree (Either c a) -> T.Tree (Either c b)+mapLeaves f (T.Node (Left x) ts) = T.Node (Left x) (map (mapLeaves f) ts)+mapLeaves f (T.Node (Right x) _) = T.Node (Right $ f x) []++-- | Map function over tree internal nodes.+mapNodes :: (a -> b) -> T.Tree (Either a c) -> T.Tree (Either b c)+mapNodes f (T.Node (Left x) ts) = T.Node (Left $ f x) (map (mapNodes f) ts)+mapNodes _ (T.Node (Right x) _) = T.Node (Right x) []+ -- | Map function over each tree from the forest. mapTrees :: (a -> b) -> T.Forest a -> T.Forest b mapTrees f = map (fmap f)  -- | Spanning of a tree.-data Span = Span-    { beg   :: Int-    , end   :: Int }+data Span w = Span+    { beg   :: w+    , end   :: w }     deriving (Show, Eq, Ord)  -- | Make span for a leaf node.-leafSpan :: Int -> Span+leafSpan :: w -> Span w leafSpan i = Span i i  -- | Minimum span overlapping both input spans.-(<>) :: Span -> Span -> Span+(<>) :: Ord w => Span w -> Span w -> Span w Span p q <> Span p' q' = Span (min p p') (max q q')+{-# INLINE (<>) #-}  -- | Set of positions covered by the span.-spanSet :: Span -> S.IntSet-spanSet s = S.fromList [beg s .. end s]+spanSet :: Ix w => Span w -> S.Set w+spanSet s = S.fromList $ range (beg s, end s)  -- | Get span of the span-annotated tree.-span :: T.Tree (a, Span) -> Span+span :: T.Tree (a, Span w) -> Span w span = snd . T.rootLabel  -- | Annotate tree nodes with spanning info given the function -- which assignes indices to leaf nodes.-spanTree :: (k -> Int) -> T.Tree k -> T.Tree (k, Span)-spanTree f (T.Node k []) = T.Node (k, leafSpan (f k)) []-spanTree f (T.Node k ts) =-    let us = spanForest f ts+spanTree :: Ord w => T.Tree (Either n w) -> T.Tree (Either n w, Span w)+spanTree (T.Node (Right k) []) = T.Node (Right k, leafSpan k) []+spanTree (T.Node k ts) =+    let us = spanForest ts         s  = foldl1 (<>) (map span us)     in  T.Node (k, s) us  -- | Annotate forest nodes with spanning info.-spanForest :: (k -> Int) -> T.Forest k -> T.Forest (k, Span)-spanForest f ts = map (spanTree f) ts+spanForest :: Ord w => T.Forest (Either n w) -> T.Forest (Either n w, Span w)+spanForest = map spanTree  -- | Remove span annotations from the tree.-unSpanTree :: T.Tree (k, Span) -> T.Tree k+unSpanTree :: T.Tree (k, Span w) -> T.Tree k unSpanTree = fmap fst  -- | Remove span annotations from the forest.-unSpanForest :: T.Forest (k, Span) -> T.Forest k+unSpanForest :: T.Forest (k, Span w) -> T.Forest k unSpanForest = map unSpanTree  -- | Sort the tree with respect to spanning info.-sortTree :: T.Tree (k, Span) -> T.Tree (k, Span)+sortTree :: Ord w => T.Tree (k, Span w) -> T.Tree (k, Span w) sortTree (T.Node x ts) = T.Node x (sortForest ts)  -- | Sort the forest with respect to spanning info.-sortForest :: T.Forest (k, Span) -> T.Forest (k, Span)+sortForest :: Ord w => T.Forest (k, Span w) -> T.Forest (k, Span w) sortForest = sortBy (comparing span) . map sortTree---- | Combine the disjoint forest with the list of words.--- Discontinuities will be patched with no trace.-addWords :: Ord k => T.Forest k -> [k] -> T.Forest k-addWords [] xs = [T.Node x [] | x <- xs]-addWords ts xs-    = unSpanForest . T.subForest-    . sortTree . fillTree-    . dummyRoot-    . spanForest f $ ts-  where-    f = (M.!) $ M.fromList (zip xs [0..])-    g = (M.!) $ M.fromList (zip [0..] xs)--    dummyRoot = T.Node (undefined, bounds)-    bounds = Span 0 (length xs - 1)--    fillForest = map fillTree-    fillTree (T.Node n []) = T.Node n []-    fillTree (T.Node (k, s) us) =-        let m = spanSet s S.\\ S.unions (map (spanSet . span) us)-            mkLeaf i = T.Node (g i, leafSpan i) []-        in  T.Node (k, s) (fillForest us ++ map mkLeaf (S.toList m))
data-named.cabal view
@@ -1,5 +1,5 @@ name:               data-named-version:            0.2.0+version:            0.3.0 synopsis:           Data types for named entities description:     The library provides data types which can be used to represent