on 3feeec2 help sign in
88 lines 2.8 kB history raw
1-- |
2-- Module : Streamly.Internal.Data.Producer
3-- Copyright : (c) 2021 Composewell Technologies
4-- License : BSD-3-Clause
5-- Maintainer : streamly@composewell.com
6-- Stability : experimental
7-- Portability : GHC
8--
9-- A 'Producer' is an 'Unfold' with an 'extract' function added to extract
10-- the state. It is more powerful but less general than an Unfold.
11--
12-- A 'Producer' represents steps of a loop generating a sequence of elements.
13-- While unfolds are closed representation of imperative loops with some opaque
14-- internal state, producers are open loops with the state being accessible to
15-- the user.
16--
17-- Unlike an unfold, which runs a loop till completion, a producer can be
18-- stopped in the middle, its state can be extracted, examined, changed, and
19-- then it can be resumed later from the stopped state.
20--
21-- A producer can be used in places where a CPS stream would otherwise be
22-- needed, because the state of the loop can be passed around. However, it can
23-- be much more efficient than CPS because it allows stream fusion and
24-- unecessary function calls can be avoided.
26module Streamly.Internal.Data.Producer
27 ( Producer (..)
29 -- * Converting
30 , simplify
32 -- * Producers
33 , nil
34 , nilM
35 , unfoldrM
36 , fromStreamD
37 , fromList
39 -- * Combinators
40 , NestedLoop (..)
41 , concat
42 )
43where
45#include "inline.hs"
47import Streamly.Internal.Data.Stream.StreamD.Step (Step(..))
48import Streamly.Internal.Data.Stream.StreamD.Type (Stream(..))
49import Streamly.Internal.Data.SVar (defState)
50import Streamly.Internal.Data.Unfold.Type (Unfold(..))
52import Streamly.Internal.Data.Producer.Type
53import Prelude hiding (concat)
55-- XXX We should write unfolds as producers where possible and define
56-- unfolds using "simplify".
57--
58-------------------------------------------------------------------------------
59-- Converting to unfolds
60-------------------------------------------------------------------------------
62-- | Simplify a producer to an unfold.
63--
64-- /Pre-release/
65{-# INLINE simplify #-}
66simplify :: Producer m a b -> Unfold m a b
67simplify (Producer step inject _) = Unfold step inject
69-------------------------------------------------------------------------------
70-- Unfolds
71-------------------------------------------------------------------------------
73-- | Convert a StreamD stream into a producer.
74--
75-- /Pre-release/
76{-# INLINE_NORMAL fromStreamD #-}
77fromStreamD :: Monad m => Producer m (Stream m a) a
78fromStreamD = Producer step return return
80 where
82 {-# INLINE_LATE step #-}
83 step (UnStream step1 state1) = do
84 r <- step1 defState state1
85 return $ case r of
86 Yield x s -> Yield x (Stream step1 s)
87 Skip s -> Skip (Stream step1 s)
88 Stop -> Stop