{-# LANGUAGE GeneralizedNewtypeDeriving, GADTs #-}------------------------------------------------------------------------------- |-- Module : Data.Acid.Common-- Copyright : PublicDomain---- Maintainer : lemmih@gmail.com-- Portability : non-portable (uses GHC extensions)---- Common structures used by the various backends (local, memory).--moduleData.Acid.CommonwhereimportData.Acid.CoreimportControl.Monad.StateimportControl.Monad.ReaderimportData.SafeCopyimportData.Serialize(runGet,runGetLazy)importControl.ApplicativeimportqualifiedData.ByteStringasStrict-- Silly fix for bug in cereal-0.3.3.0's version of runGetLazy.runGetLazyFixgetterinp=caserunGetgetterStrict.emptyofLeftmsg->runGetLazygetterinpRightval->Rightvalclass(SafeCopyst)=>IsAcidicstwhereacidEvents::[Eventst]-- ^ List of events capable of updating or querying the state.-- | Context monad for Update events.newtypeUpdatesta=Update{unUpdate::Statesta}deriving(Monad,Functor,MonadStatest)-- mtl pre-2.0 doesn't have these instances to newtype-derive, but they're-- simple enough.instanceApplicative(Updatest)wherepure=return(<*>)=ap-- | Context monad for Query events.newtypeQuerysta=Query{unQuery::Readersta}deriving(Monad,Functor,MonadReaderst)instanceApplicative(Queryst)wherepure=return(<*>)=ap-- | Run a query in the Update Monad.runQuery::Querysta->UpdatestarunQueryquery=dost<-getreturn(runReader(unQueryquery)st)-- | Events return the same thing as Methods. The exact type of 'EventResult'-- depends on the event.typeEventResultev=MethodResultevtypeEventStateev=MethodStateev-- | We distinguish between events that modify the state and those that do not.---- UpdateEvents are executed in a MonadState context and have to be serialized-- to disk before they are considered durable.---- QueryEvents are executed in a MonadReader context and obviously do not have-- to be serialized to disk.dataEventstwhereUpdateEvent::UpdateEventev=>(ev->Update(EventStateev)(EventResultev))->Event(EventStateev)QueryEvent::QueryEventev=>(ev->Query(EventStateev)(EventResultev))->Event(EventStateev)-- | All UpdateEvents are also Methods.classMethodev=>UpdateEventev-- | All QueryEvents are also Methods.classMethodev=>QueryEventeveventsToMethods::[Eventst]->[MethodContainerst]eventsToMethods=mapworkerwhereworker::Eventst->MethodContainerstworker(UpdateEventfn)=Method(unUpdate.fn)worker(QueryEventfn)=Method(\ev->dost<-getreturn(runReader(unQuery$fnev)st))