streamly-0.8.1: src/Streamly/Internal/Data/Producer.hs
-- |
-- Module : Streamly.Internal.Data.Producer
-- Copyright : (c) 2021 Composewell Technologies
-- License : BSD-3-Clause
-- Maintainer : streamly@composewell.com
-- Stability : experimental
-- Portability : GHC
--
-- A 'Producer' is an 'Unfold' with an 'extract' function added to extract
-- the state. It is more powerful but less general than an Unfold.
--
-- A 'Producer' represents steps of a loop generating a sequence of elements.
-- While unfolds are closed representation of imperative loops with some opaque
-- internal state, producers are open loops with the state being accessible to
-- the user.
--
-- Unlike an unfold, which runs a loop till completion, a producer can be
-- stopped in the middle, its state can be extracted, examined, changed, and
-- then it can be resumed later from the stopped state.
--
-- A producer can be used in places where a CPS stream would otherwise be
-- needed, because the state of the loop can be passed around. However, it can
-- be much more efficient than CPS because it allows stream fusion and
-- unecessary function calls can be avoided.
module Streamly.Internal.Data.Producer
( Producer (..)
-- * Converting
, simplify
-- * Producers
, nil
, nilM
, unfoldrM
, fromStreamD
, fromList
-- * Combinators
, NestedLoop (..)
, concat
)
where
#include "inline.hs"
import Streamly.Internal.Data.Stream.StreamD.Step (Step(..))
import Streamly.Internal.Data.Stream.StreamD.Type (Stream(..))
import Streamly.Internal.Data.SVar.Type (defState)
import Streamly.Internal.Data.Unfold.Type (Unfold(..))
import Streamly.Internal.Data.Producer.Type
import Prelude hiding (concat)
-- XXX We should write unfolds as producers where possible and define
-- unfolds using "simplify".
--
-------------------------------------------------------------------------------
-- Converting to unfolds
-------------------------------------------------------------------------------
-- | Simplify a producer to an unfold.
--
-- /Pre-release/
{-# INLINE simplify #-}
simplify :: Producer m a b -> Unfold m a b
simplify (Producer step inject _) = Unfold step inject
-------------------------------------------------------------------------------
-- Unfolds
-------------------------------------------------------------------------------
-- | Convert a StreamD stream into a producer.
--
-- /Pre-release/
{-# INLINE_NORMAL fromStreamD #-}
fromStreamD :: Monad m => Producer m (Stream m a) a
fromStreamD = Producer step return return
where
{-# INLINE_LATE step #-}
step (UnStream step1 state1) = do
r <- step1 defState state1
return $ case r of
Yield x s -> Yield x (Stream step1 s)
Skip s -> Skip (Stream step1 s)
Stop -> Stop