{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-} module Events.Types ( TimeRange(..), rangeStart, rangeDuration , Event(..), payload, occursWithin , EvalCtx(..), ctxVars, ctxEvents , ObjCtx(..), objOccurs, objPayload , Eval, evaluate , module Data.Aeson , module Data.Time.Clock , module Data.Default.Class ) where import Control.Lens.TH import Data.Aeson (Object) import Data.Time.Clock import Control.Monad.State.Lazy import ListT (ListT) import qualified ListT import Data.Default.Class import Data.Monoid import Control.Monad.Fix import Control.Lens import Data.Maybe import Debug.Trace data TimeRange = TimeRange { _rangeStart :: UTCTime , _rangeDuration :: NominalDiffTime } makeLenses ''TimeRange data Event = Event { _payload :: Object , _occursWithin :: TimeRange -> Bool } makeLenses ''Event data EvalCtx = EvalCtx { _ctxVars :: Object , _ctxEvents :: [Object] } deriving (Show) makeLenses ''EvalCtx instance Default EvalCtx where def = EvalCtx { _ctxVars = mempty , _ctxEvents = mempty } data ObjCtx = ObjCtx { _objOccurs :: Bool , _objPayload :: Maybe Object } makeLenses ''ObjCtx instance Default ObjCtx where def = ObjCtx { _objOccurs = False , _objPayload = Nothing } objCtx :: ObjCtx -> Maybe Object objCtx (ObjCtx False _) = Nothing objCtx (ObjCtx True o) = o type Eval m a = StateT ObjCtx (ListT (StateT EvalCtx m)) a evaluate :: MonadFix m => Eval m () -> m [Object] evaluate x = catMaybes <$> mfix x' where x' = evalStateT (ListT.toList (objCtx <$> execStateT x def)) . flip (set ctxEvents) def . catMaybes instance MonadState s m => MonadState s (ListT m) where get = lift get put = lift . put