packages feed

effet-0.3.0.2: examples/Example/Writer.hs

-- | Examples of the writer effect.
module Example.Writer where

-- base
import Data.Monoid (Sum(Sum), getSum)

-- hspec
import Test.Hspec (Spec, it, shouldBe)

-- effet
import Control.Effect.Identity
import Control.Effect.State
import Control.Effect.Writer
import qualified Control.Effect.State.Lazy    as L
import qualified Control.Effect.Writer.Lazy   as L
import qualified Control.Effect.Writer.Strict as S

--- Example Programs -----------------------------------------------------------

-- | Write something in a sub-action, capture it and tell something again.
sumWriter :: Writer (Sum Int) m => m Int
sumWriter = do
  (w,a) <- listen $ do tell 5
                       pure 8
  tell w
  tell a
  pure $ getSum (w + a)

-- | Combines the state and writer effect.
stateWriter :: (State Int m, Writer [Int] m) => m Int
stateWriter = do
  tell [1,2,3]
  num <- get
  tell [num, num + 1, num + 2]
  pure num

-- | Censors (modifies) the output of sumWriter.
censorWriter :: Writer (Sum Int) m => m Int
censorWriter = censor (fmap (+1)) sumWriter

--- Test Cases -----------------------------------------------------------------

spec :: Spec
spec = do
  it "listens to sub-action writings" $
    ( runIdentity    -- result:  (Sum Int, Int)
    . S.runWriter    -- result:  Monad m => m (Sum Int, Int)
    $ sumWriter )    -- effects: Writer (Sum Int)
      `shouldBe`
        (Sum 18, 13)
  it "combines state and writer" $
    ( runIdentity    -- result:  ([Int], Int)
    . L.runWriter    -- result:  Monad m => m ([Int], Int)
    . L.execState 4  -- effects: Writer [Int]
    $ stateWriter )  -- effects: State Int, Writer [Int]
      `shouldBe`
        ([1,2,3,4,5,6], 4)
  it "censors/modifies output" $
    ( runIdentity    -- result:  (Sum Int, Int)
    . L.runWriter    -- result:  Monad m => m (Sum Int, Int)
    $ censorWriter ) -- effects: Writer (Sum Int)
      `shouldBe`
        (Sum 19, 13)