packages feed

associative-0.0.1: examples/Data/Associative/Examples/SemigroupOpExamples.hs

{-# OPTIONS_GHC -Wall -Werror #-}

-- |
-- Example usages of "Data.Associative.SemigroupOp".
module Data.Associative.Examples.SemigroupOpExamples
  ( -- * Constructing and running total semigroup operations
    add,
    cat,

    -- * Combining operations with Semigroup (pointwise)
    pointwiseExample,

    -- * Functor and Profunctor
    fmapTotalExample,
    lmapExample,

    -- * Using effects (monad transformer)
    statefulConcat,
  )
where

import Control.Monad.State (State, get, put)
import Data.Associative.SemigroupOp
  ( SemigroupOp',
    SemigroupOpT (..),
    op,
    runSemigroupOp,
    runSemigroupOpT,
  )
import Data.Functor.Identity (Identity (..))

-- $setup
-- >>> import Data.Functor.Identity (Identity(..))
-- >>> import Data.Profunctor (lmap, rmap)
-- >>> import Control.Monad.State (runState)

-- * Constructing and running total semigroup operations

-- | A total semigroup operation for addition.
--
-- >>> runSemigroupOp add 3 4
-- 7
add :: SemigroupOp' Int
add = op (+)

-- | A total semigroup operation for list concatenation.
--
-- >>> runSemigroupOp cat [1,2] [3,4 :: Int]
-- [1,2,3,4]
cat :: SemigroupOp' [Int]
cat = op (++)

-- * Combining operations with Semigroup (pointwise)

-- | Total semigroup operations combine pointwise: both operations
-- run and their results are combined via the inner 'Semigroup'.
--
-- >>> runSemigroupOp (cat <> cat) [1] [2 :: Int]
-- [1,2,1,2]
pointwiseExample :: SemigroupOp' [Int]
pointwiseExample = cat <> cat

-- * Functor and Profunctor

-- | 'fmap' transforms the result of a total operation.
--
-- >>> runSemigroupOpT (fmap show add) 3 4
-- Identity "7"
fmapTotalExample :: SemigroupOpT Identity Int String
fmapTotalExample = fmap show add

-- | 'lmap' transforms the inputs (contravariantly).
--
-- >>> runSemigroupOp (lmap negate add) (-3) (-4)
-- 7
--
-- 'rmap' transforms the output (same as 'fmap').
--
-- >>> runSemigroupOp (rmap (*10) add) 3 4
-- 70
lmapExample :: SemigroupOp' Int
lmapExample = fmap (* 10) add

-- * Using effects (monad transformer)

-- | A total semigroup operation with state.
--
-- >>> runState (runSemigroupOpT statefulConcat "hello" " world") 0
-- ("hello world",1)
statefulConcat :: SemigroupOpT (State Int) String String
statefulConcat =
  SemigroupOpT
    ( \a b -> do
        n <- get
        put (n + 1)
        pure (a ++ b)
    )

-- helpers to suppress unused-import warnings for re-exports used in doctests
_suppressRunSemigroupOp :: SemigroupOp' a -> a -> a -> a
_suppressRunSemigroupOp = runSemigroupOp

_suppressRunSemigroupOpT :: SemigroupOpT f a b -> a -> a -> f b
_suppressRunSemigroupOpT = runSemigroupOpT