{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Telegram.Bot.Simple.Eff where
import Control.Monad.Reader
import Control.Monad.Writer
import Data.Bifunctor
import Servant.Client
import qualified Telegram.Bot.API as Telegram
newtype BotM a = BotM { _runBotM :: ReaderT BotContext ClientM a }
deriving (Functor, Applicative, Monad, MonadReader BotContext, MonadIO)
data BotContext = BotContext
{ botContextUser :: Telegram.User
, botContextUpdate :: Maybe Telegram.Update
}
liftClientM :: ClientM a -> BotM a
liftClientM = BotM . lift
runBotM :: BotContext -> BotM a -> ClientM a
runBotM update = flip runReaderT update . _runBotM
newtype Eff action model = Eff { _runEff :: Writer [BotM action] model }
deriving (Functor, Applicative, Monad)
instance Bifunctor Eff where
bimap f g = Eff . mapWriter (bimap g (map (fmap f))) . _runEff
runEff :: Eff action model -> (model, [BotM action])
runEff = runWriter . _runEff
eff :: BotM a -> Eff a ()
eff e = Eff (tell [e])
withEffect :: BotM action -> model -> Eff action model
withEffect effect model = eff effect >> pure model
(<#) :: model -> BotM action -> Eff action model
(<#) = flip withEffect
setBotMUpdate :: Maybe Telegram.Update -> BotM a -> BotM a
setBotMUpdate update (BotM m) = BotM (local f m)
where
f botContext = botContext { botContextUpdate = update }
setEffUpdate :: Maybe Telegram.Update -> Eff action model -> Eff action model
setEffUpdate update (Eff m) = Eff (censor (map (setBotMUpdate update)) m)