doc-review-0.7: src/State/Mem.hs
module State.Mem
( new
)
where
import State.Types
import Data.Maybe ( listToMaybe, fromMaybe )
import Data.Function ( on )
import Data.List ( sortBy )
import Control.Monad ( mplus )
import qualified Data.Sequence as S
import qualified Data.Set as Set
import qualified Data.Map as Map
import Data.Foldable ( toList )
import Control.Concurrent.MVar ( newMVar, withMVar, modifyMVar_ )
import Control.Arrow ( second, (***) )
import Network.URI ( URI )
--------------------------------------------------
-- Stateful
new :: IO State
new = do
v <- newMVar emptyMemState
return $ State
{ findComments = \cId ->
withMVar v $
return . maybe [] toList . Map.lookup cId . cms
, getCounts = \chId ->
withMVar v $ return . getCounts' chId
, addComment = \cId chId c ->
modifyMVar_ v $ return . addComment' cId chId c
, addChapter = \chId cIds mURI ->
modifyMVar_ v $ return . addChapter' chId cIds mURI
, getLastInfo = \sid ->
withMVar v $ return . getInfo' sid
, getChapterComments =
\chId -> withMVar v $ return . getChapterComments' chId
, getChapterURI = \chId -> withMVar v $ return . chapterURI chId
}
--------------------------------------------------
-- Pure
data MemState = MemState { chs :: Map.Map ChapterId (Maybe URI, Set.Set CommentId)
, cms :: Map.Map CommentId (S.Seq Comment)
}
chapterComments :: ChapterId -> MemState -> Set.Set CommentId
chapterComments chId = maybe Set.empty snd . Map.lookup chId . chs
chapterURI :: ChapterId -> MemState -> Maybe URI
chapterURI chId st = fst =<< Map.lookup chId (chs st)
withChapterComments :: (Set.Set CommentId -> Set.Set CommentId)
-> ChapterId -> MemState -> MemState
withChapterComments = withChapter . second
withChapter :: ((Maybe URI, Set.Set CommentId) -> (Maybe URI, Set.Set CommentId))
-> ChapterId -> MemState -> MemState
withChapter f chId st =
let upd x = case f $ fromMaybe (Nothing, Set.empty) x of
(Nothing, s) | Set.null s -> Nothing
p -> Just p
in st { chs = Map.alter upd chId $ chs st }
emptyMemState :: MemState
emptyMemState = MemState Map.empty Map.empty
getInfo' :: SessionId -> MemState -> Maybe SessionInfo
getInfo' sId =
fmap toInfo .
listToMaybe .
take 1 .
reverse .
sortBy (compare `on` cDate) .
filter ((== sId) . cSession) .
concatMap toList .
Map.elems .
cms
where
toInfo c = SessionInfo (cName c) (cEmail c)
getCounts' :: Maybe ChapterId -> MemState -> [(CommentId, Int)]
getCounts' mChId st =
map (second S.length) $ Map.toList $
case mChId of
Nothing -> cms st
Just chId ->
let cIds = chapterComments chId st
p k _ = k `Set.member` cIds
in Map.filterWithKey p (cms st)
addChapter' :: ChapterId -> [CommentId] -> Maybe URI -> MemState -> MemState
addChapter' chId cIds mURI =
withChapter ((mURI `mplus`) *** (Set.union $ Set.fromList cIds)) chId
addComment' :: CommentId -> Maybe ChapterId -> Comment -> MemState -> MemState
addComment' cId mChId c st =
maybe id (withChapterComments (Set.insert cId)) mChId $
st { cms = Map.alter (addSeq c) cId $ cms st }
where
addSeq x = return . (S.|> x) . maybe S.empty id
getChapterComments' :: ChapterId -> MemState -> [(CommentId, Comment)]
getChapterComments' chId st =
let sortDateDesc = sortBy $ flip (compare `on` (cDate . snd))
lookupComments cId = maybe [] (map ((,) cId) . toList) $
Map.lookup cId $ cms st
in sortDateDesc $ concatMap lookupComments $
toList $ chapterComments chId st