{-# LANGUAGE GeneralizedNewtypeDeriving, GADTs #-}
module Data.Acid.Common where
import Data.Acid.Core
import Control.Monad.State
import Control.Monad.Reader
import Data.ByteString.Lazy ( ByteString )
import Data.SafeCopy
import Data.Serialize ( Get, runGet, runGetLazy )
import Control.Applicative
import qualified Data.ByteString as Strict
runGetLazyFix :: Get a
-> ByteString
-> Either String a
runGetLazyFix getter inp
= case runGet getter Strict.empty of
Left _msg -> runGetLazy getter inp
Right val -> Right val
class (SafeCopy st) => IsAcidic st where
acidEvents :: [Event st]
newtype Update st a = Update { unUpdate :: State st a }
deriving (Monad, Functor, MonadState st)
instance Applicative (Update st) where
pure = return
(<*>) = ap
newtype Query st a = Query { unQuery :: Reader st a }
deriving (Monad, Functor, MonadReader st)
instance Applicative (Query st) where
pure = return
(<*>) = ap
liftQuery :: Query st a -> Update st a
liftQuery query
= do st <- get
return (runReader (unQuery query) st)
type EventResult ev = MethodResult ev
type EventState ev = MethodState ev
data Event st where
UpdateEvent :: UpdateEvent ev => (ev -> Update (EventState ev) (EventResult ev)) -> Event (EventState ev)
QueryEvent :: QueryEvent ev => (ev -> Query (EventState ev) (EventResult ev)) -> Event (EventState ev)
class Method ev => UpdateEvent ev
class Method ev => QueryEvent ev
eventsToMethods :: [Event st] -> [MethodContainer st]
eventsToMethods = map worker
where worker :: Event st -> MethodContainer st
worker (UpdateEvent fn) = Method (unUpdate . fn)
worker (QueryEvent fn) = Method (\ev -> do st <- get
return (runReader (unQuery $ fn ev) st)
)