{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE TypeOperators #-} -- | -- Module: Control.Monad.Freer.StateRW -- Description: State effects in terms of Reader and Writer. -- Copyright: (c) 2016 Allele Dev; 2017 Ixperta Solutions s.r.o. -- License: BSD3 -- Maintainer: ixcom-core@ixperta.com -- Stability: experimental -- Portability: GHC specific language extensions. -- -- Composable handler for 'State' effects in terms of 'Reader' and 'Writer' -- effects. This module is more a tutorial on how to compose handlers. It is -- slightly slower than a dedicated 'State' handler. -- -- Using as a starting point. module Control.Monad.Freer.StateRW ( runStateR , Reader , Writer , tell , ask ) where import Control.Monad (return) import Data.Either (Either(Left, Right)) import Control.Monad.Freer.Reader (Reader(Reader), ask) import Control.Monad.Freer.Writer (Writer(Writer), tell) import Control.Monad.Freer.Internal (Eff(E, Val), decomp, qComp, tsingleton) -- | State handler, using 'Reader' and 'Writer' effects. runStateR :: Eff (Writer s ': Reader s ': effs) a -> s -> Eff effs (a, s) runStateR m s = loop s m where loop :: s -> Eff (Writer s ': Reader s ': effs) a -> Eff effs (a, s) loop s' (Val x) = return (x, s') loop s' (E u q) = case decomp u of Right (Writer o) -> k o () Left u' -> case decomp u' of Right Reader -> k s' s' Left u'' -> E u'' (tsingleton (k s')) where k s'' = qComp q (loop s'')