{-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE FlexibleInstances #-} module Hunt.Common.IntermediateValue where import Control.Arrow (second) import Control.DeepSeq import Data.Aeson import Data.Binary (Binary) import qualified Data.List as L import Hunt.Common.Occurrences (Occurrences) import qualified Hunt.Common.Occurrences as Occ import Hunt.Common.DocIdSet (DocIdSet (..)) import qualified Hunt.Common.DocIdSet as DS import qualified Hunt.Common.DocIdMap as DM -- This type represents the interface for a value to the engine -- To have an easy first implementaton the intermediate is -- basically the same as Occurrences, but that can be adjusted later newtype IntermediateValue = IntermediateValue { unIntermediate :: Occurrences } deriving (Show, Eq) mkIntermediateValue :: Occurrences -> IntermediateValue mkIntermediateValue o = IntermediateValue $! o instance NFData IntermediateValue where rnf (IntermediateValue occ) = rnf occ instance ToJSON IntermediateValue where toJSON x = toJSON (fromIntermediate x :: Occurrences) fromIntermediates :: IndexValue u => [(x, IntermediateValue)] -> [(x, u)] fromIntermediates xs = L.map (second fromIntermediate) xs fromScoredIntermediates :: IndexValue u => [(x, (s, IntermediateValue))] -> [(x, (s,u))] fromScoredIntermediates xs = L.map (\(x,u) -> (x, second fromIntermediate $ u)) xs toIntermediates :: IndexValue u => [(x,u)] -> [(x, IntermediateValue)] toIntermediates xs = L.map (second toIntermediate) xs class (Binary x, NFData x) => IndexValue x where toIntermediate :: x -> IntermediateValue fromIntermediate :: IntermediateValue -> x mergeValues :: x -> x -> x diffValues :: DocIdSet -> x -> Maybe x instance IndexValue Occurrences where toIntermediate x = mkIntermediateValue x fromIntermediate x = unIntermediate $! x mergeValues = Occ.merge diffValues s m = let z = Occ.diffWithSet m s in if Occ.null z then Nothing else Just z mapToSet :: Occurrences -> DocIdSet mapToSet = DS.fromList . DM.keys instance IndexValue DocIdSet where toIntermediate = mkIntermediateValue . Occ.fromDocIdSet fromIntermediate = mapToSet . fromIntermediate mergeValues = DS.union diffValues s1 s2 = let r = DS.difference s2 s1 in if DS.null r then Nothing else Just r