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 :: forall a b. (a -> b) -> Aggregation m a a -> Aggregation m a b
fmap a -> b
f Aggregation {m x
begin :: ()
begin :: m x
begin, x -> a -> m x
step :: ()
step :: x -> a -> m x
step, x -> m a
done :: ()
done :: x -> m a
done} =
    Aggregation {m x
begin :: m x
begin :: m x
begin, x -> a -> m x
step :: x -> a -> m x
step :: x -> a -> m x
step, done :: x -> m b
done = (a -> b) -> m a -> m b
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f (m a -> m b) -> (x -> m a) -> x -> m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. x -> m a
done}

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

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

listAggregation :: Applicative m => Aggregation m a [a]
listAggregation :: forall (m :: * -> *) a. Applicative m => Aggregation m a [a]
listAggregation = Seq a -> [a]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Seq a -> [a]) -> Aggregation m a (Seq a) -> Aggregation m a [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Aggregation m a (Seq a)
forall (m :: * -> *) a. Applicative m => Aggregation m a (Seq a)
seqAggregation