-- | Some interesting examples of effectful folds
module Fold.Effectful.Examples.Interesting where

import Fold.Effectful.Type

import Control.Monad (Monad)
import Data.Functor (void)
import Data.Monoid (Monoid, mempty)
import Data.Semigroup ((<>))
import Prelude (($!))

import qualified Control.Applicative as Applicative

{-| Performs an action for each input, discarding the result -}
effect :: Monad m => (a -> m b) -> EffectfulFold m a ()
effect :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> EffectfulFold m a ()
effect a -> m b
f = forall w (m :: * -> *) a.
(Monoid w, Monad m) =>
(a -> m w) -> EffectfulFold m a w
effectMonoid (\a
a -> forall (f :: * -> *) a. Functor f => f a -> f ()
void (a -> m b
f a
a))

{-| Performs an action for each input, monoidally combining the results
from all the actions. -}
effectMonoid ::  (Monoid w, Monad m) => (a -> m w) -> EffectfulFold m a w
effectMonoid :: forall w (m :: * -> *) a.
(Monoid w, Monad m) =>
(a -> m w) -> EffectfulFold m a w
effectMonoid a -> m w
act = EffectfulFold
    { initial :: m w
initial = forall (f :: * -> *) a. Applicative f => a -> f a
Applicative.pure forall a. Monoid a => a
mempty
    , step :: w -> a -> m w
step = \w
m a
a -> do{ w
m' <- a -> m w
act a
a; forall (f :: * -> *) a. Applicative f => a -> f a
Applicative.pure forall a b. (a -> b) -> a -> b
$! forall a. Semigroup a => a -> a -> a
(<>) w
m w
m' }
    , extract :: w -> m w
extract = forall (f :: * -> *) a. Applicative f => a -> f a
Applicative.pure
    }