module Hunt.Common.Occurrences
where
import Prelude hiding (subtract)
import Hunt.Common.BasicTypes
import Hunt.Common.DocId
import Hunt.Common.DocIdMap (DocIdMap)
import Hunt.Common.DocIdSet (DocIdSet)
import qualified Hunt.Common.DocIdMap as DM
import Hunt.Common.Positions (Positions)
import qualified Hunt.Common.Positions as Pos
type Occurrences = DocIdMap Positions
empty :: Occurrences
empty = DM.empty
fromDocIdSet :: DocIdSet -> Occurrences
fromDocIdSet s = DM.fromDocIdSet (\_ -> Pos.singleton 1) s
singleton :: DocId -> Position -> Occurrences
singleton d p = singleton' d [p]
singleton' :: DocId -> [Position] -> Occurrences
singleton' d ps = DM.insert d (Pos.fromList ps) DM.empty
null :: Occurrences -> Bool
null = DM.null
size :: Occurrences -> Int
size = DM.foldr ((+) . Pos.size) 0
insert :: DocId -> Position -> Occurrences -> Occurrences
insert d p = DM.insertWith Pos.union d (Pos.singleton p)
insert' :: DocId -> Positions -> Occurrences -> Occurrences
insert' d ps occs = Pos.foldr (insert d) occs ps
deleteOccurrence :: DocId -> Position -> Occurrences -> Occurrences
deleteOccurrence d p = subtract (DM.singleton d (Pos.singleton p))
delete :: DocId -> Occurrences -> Occurrences
delete = DM.delete
update :: (DocId -> DocId) -> Occurrences -> Occurrences
update f = DM.foldrWithKey
(\ d ps res -> DM.insertWith Pos.union (f d) ps res) empty
merge :: Occurrences -> Occurrences -> Occurrences
merge = DM.unionWith Pos.union
merges :: [Occurrences] -> Occurrences
merges = DM.unionsWith Pos.union
difference :: Occurrences -> Occurrences -> Occurrences
difference = DM.difference
diffWithSet :: Occurrences -> DocIdSet -> Occurrences
diffWithSet = DM.diffWithSet
subtract :: Occurrences -> Occurrences -> Occurrences
subtract = DM.differenceWith subtractPositions
where
subtractPositions p1 p2
= if Pos.null diffPos
then Nothing
else Just diffPos
where
diffPos = Pos.difference p1 p2
intersectOccurrences :: (Positions -> Positions -> Positions) ->
Occurrences -> Occurrences -> Occurrences
intersectOccurrences pf os1 os2
= DM.filter (not . Pos.null) $ DM.intersectionWith pf os1 os2