changeset-0.1.0.0: examples-mtl23/Control/Monad/Trans/Changeset/AccumExample.hs
{-# OPTIONS_GHC -Wno-orphans #-}
module Control.Monad.Trans.Changeset.AccumExample where
-- base
import Data.Functor.Identity (Identity)
import Data.Tuple (swap)
-- transformers
import Control.Monad.Trans.Accum (runAccum)
-- mtl
import Control.Monad.Accum (MonadAccum (..))
import Control.Monad.Changeset.Class (MonadChangeset (changeset))
-- monoid-extras
import Data.Monoid.Action (Regular (Regular, getRegular))
-- changeset
import Control.Monad.Trans.Changeset
-- tasty
import Test.Tasty (TestTree)
-- tasty-hunit
import Test.Tasty.HUnit (testCase, (@?=))
-- | The 'AccumT' monad transformer is a special case of 'ChangesetT' when both state and change are the same type.
type RegularAccumT w = ChangesetT (Regular w) w
instance {-# OVERLAPPING #-} (Monoid w, Monad m) => MonadAccum w (RegularAccumT w m) where
accum = changeset . (. getRegular)
exampleProgram :: (MonadAccum (Changes (ListChange Int)) m) => m (Changes (ListChange Int))
exampleProgram = do
add $ singleChange (Cons 1)
add $ singleChange (Cons 2)
ns <- look
add $ singleChange (Cons 3)
pure ns
initialState :: Changes (ListChange Int)
initialState = singleChange $ Cons 0
tests :: TestTree
tests = testCase "Accum" $ runAccum exampleProgram initialState @?= swap (getChangeset (exampleProgram :: RegularAccumT (Changes (ListChange Int)) Identity (Changes (ListChange Int))) (Regular initialState))