packages feed

yield-0.0.0.0: library/Control/Monad/Yield/Aggregation.hs

module Control.Monad.Yield.Aggregation
  ( Aggregation (..)
  , noAggregation
  , seqAggregation
  , listAggregation
  ) where

import Data.Foldable (toList)
import Data.Sequence (Seq (..))
import Prelude (Applicative (..), Functor (..), (.), (<$>))

-- | An effectful stream consumer
--
-- The type parameter @x@ represents the consumer's internal state.
data Aggregation m a b = forall x.
  Aggregation
  { begin :: m x
  -- ^ Produce the initial state
  , step :: x -> a -> m x
  -- ^ Consume one item from the stream
  , done :: x -> m b
  -- ^ Produce the final result
  }

instance Functor m => Functor (Aggregation m a) where
  fmap f Aggregation {begin, step, done} =
    Aggregation {begin, step, done = fmap f . done}

noAggregation :: Applicative m => Aggregation m a ()
noAggregation = Aggregation {begin = pure (), step = \() _ -> pure (), done = pure}

seqAggregation :: Applicative m => Aggregation m a (Seq a)
seqAggregation = Aggregation {begin = pure Empty, step = \xs -> pure . (xs :|>), done = pure}

listAggregation :: Applicative m => Aggregation m a [a]
listAggregation = toList <$> seqAggregation