-- | 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  .
censorWriter :: Writer (Sum Int) m => m Int
censorWriter = censor (fmap (+1)) sumWriter

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

spec :: Spec
spec = do
  it "listens to sub-action writings" $
  result :   ( Sum Int , Int )
  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)
  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" $
  result :   ( Sum Int , Int )
  result :   Monad m = > m ( Sum Int , Int )
    $ censorWriter ) -- effects: Writer (Sum Int)
      `shouldBe`
        (Sum 19, 13)
 | Examples of the writer effect.
 base
 effet
- Example Programs -----------------------------------------------------------
 | Write something in a sub-action, capture it and tell something again.
 | Combines the state and writer effect.
- Test Cases -----------------------------------------------------------------
 effects: Writer (Sum Int)
 result:  ([Int], Int)
 effects: Writer [Int]
 effects: State Int, Writer [Int]
 effects: Writer (Sum Int)
module Example.Writer where

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

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

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


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)

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  .
censorWriter :: Writer (Sum Int) m => m Int
censorWriter = censor (fmap (+1)) sumWriter


spec :: Spec
spec = do
  it "listens to sub-action writings" $
  result :   ( Sum Int , Int )
  result :   Monad m = > m ( Sum Int , Int )
      `shouldBe`
        (Sum 18, 13)
  it "combines state and writer" $
  result :   Monad m = > m ( [ Int ] , Int )
      `shouldBe`
        ([1,2,3,4,5,6], 4)
  it "censors/modifies output" $
  result :   ( Sum Int , Int )
  result :   Monad m = > m ( Sum Int , Int )
      `shouldBe`
        (Sum 19, 13)