HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Modulestreamly-core-0.2.2Haskell2010

Streamly.Internal.Data.Unfold

  • 3 types
  • 1 class
  • 96 values

Setup

0 declarations

To execute the code examples provided in this module in ghci, please run the following commands first.

Example5 expressions
:mimport Streamly.Data.Unfold (Unfold)import qualified Streamly.Data.Fold as Foldimport qualified Streamly.Data.Stream as Streamimport qualified Streamly.Data.Unfold as Unfold

For APIs that have not been released yet.

Example1 expression
import qualified Streamly.Internal.Data.Unfold as Unfold

Unfold Type

39 declarations
valuelmapM :: Monad m => (a -> m c) -> Unfold m c b -> Unfold m a b
#

Map an action on the input argument of the Unfold.

lmapM f = Unfold.many (Unfold.functionM f)
datadata Step s a
#

A stream is a succession of Steps. A Yield produces a single value and the next state of the stream. Stop indicates there are no more values in the stream.

Constructors

Instances1Functor
  • Functor (Step s)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Stream.Step
datadata Unfold (m :: Type -> Type) a b
#

An Unfold m a b is a generator of a stream of values of type b from a seed of type a in Monad m.

Constructors

  • forall s. Unfold (s -> m (Step s b)) (a -> m s)
    Unfold step inject
Instances1Functor
  • Functor m => Functor (Unfold m a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Type

    Maps a function on the output of the unfold (the type b).

valuemapM :: Monad m => (b -> m c) -> Unfold m a b -> Unfold m a c
#

Apply a monadic function to each element of the stream and replace it with the output of the resulting action.

Example1 expression
mapM f = Unfold.mapM2 (const f)
valuezipWith
  1. :: Monad m
  2. => b -> c -> d
  3. -> Unfold m a b
  4. -> Unfold m a c
  5. -> Unfold m a d
#

Like zipWithM but with a pure zip function.

Example4 expressions
square = fmap (\x -> x * x) Unfold.fromListcube = fmap (\x -> x * x * x) Unfold.fromListu = Unfold.zipWith (,) square cubeUnfold.fold Fold.toList u [1..5][(1,1),(4,8),(9,27),(16,64),(25,125)]
zipWith f = zipWithM (\a b -> return $ f a b)
valuezipWithM
  1. :: Monad m
  2. => b -> c -> m d
  3. -> Unfold m a b
  4. -> Unfold m a c
  5. -> Unfold m a d
#

Distribute the input to two unfolds and then zip the outputs to a single stream using a monadic zip function.

Stops as soon as any of the unfolds stops.

Pre-release

valuemap :: Functor m => (b -> c) -> Unfold m a b -> Unfold m a c
#

Map a function on the output of the unfold (the type b).

Example1 expression
map f = Unfold.map2 (const f)

Pre-release

valuefromEffect :: Applicative m => m b -> Unfold m a b
#

The unfold discards its input and generates a function stream using the supplied monadic action.

Pre-release

valuefirst :: a -> Unfold m (a, b) c -> Unfold m b c
#

Supply the first component of the tuple to an unfold that accepts a tuple as a seed resulting in a fold that accepts the second component of the tuple as a seed.

first a = Unfold.lmap (a, )

Pre-release

valuemany :: Monad m => Unfold m b c -> Unfold m a b -> Unfold m a c
#

Apply the first unfold to each output element of the second unfold and flatten the output in a single stream.

Example1 expression
many u = Unfold.many2 (Unfold.lmap snd u)
valuesecond :: b -> Unfold m (a, b) c -> Unfold m a c
#

Supply the second component of the tuple to an unfold that accepts a tuple as a seed resulting in a fold that accepts the first component of the tuple as a seed.

second b = Unfold.lmap (, b)

Pre-release

valuelmap :: (a -> c) -> Unfold m c b -> Unfold m a b
#

Map a function on the input argument of the Unfold.

Example2 expressions
u = Unfold.lmap (fmap (+1)) Unfold.fromListUnfold.fold Fold.toList u [1..5][2,3,4,5,6]
lmap f = Unfold.many (Unfold.function f)
valueunfoldr :: Applicative m => (a -> Maybe (b, a)) -> Unfold m a b
#

Like unfoldrM but uses a pure step function.

Example1 expression
:{ f [] = Nothing f (x:xs) = Just (x, xs):}
Example1 expression
Unfold.fold Fold.toList (Unfold.unfoldr f) [1,2,3][1,2,3]
valueunfoldrM :: Applicative m => (a -> m (Maybe (b, a))) -> Unfold m a b
#

Build a stream by unfolding a monadic step function starting from a seed. The step function returns the next element in the stream and the next seed value. When it is done it returns Nothing and the stream ends.

valuecrossWith
  1. :: Monad m
  2. => b -> c -> d
  3. -> Unfold m a b
  4. -> Unfold m a c
  5. -> Unfold m a d
#

Like crossWithM but uses a pure combining function.

crossWith f = crossWithM (\b c -> return $ f b c)
Example4 expressions
u1 = Unfold.lmap fst Unfold.fromListu2 = Unfold.lmap snd Unfold.fromListu = Unfold.crossWith (,) u1 u2Unfold.fold Fold.toList u ([1,2,3], [4,5,6])[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]
valueconcatMapM
  1. :: Monad m
  2. => b -> m (Unfold m a c)
  3. -> Unfold m a b
  4. -> Unfold m a c
#

Map an unfold generating action to each element of an unfold and flatten the results into a single stream.

valuefunction :: Applicative m => (a -> b) -> Unfold m a b
#

Lift a pure function into an unfold. The unfold generates a singleton stream.

function f = functionM $ return . f
valuefunctionM :: Applicative m => (a -> m b) -> Unfold m a b
#

Lift a monadic function into an unfold. The unfold generates a singleton stream.

valuecross :: Monad m => Unfold m a b -> Unfold m a c -> Unfold m a (b, c)
#

See crossWith.

Definition:

Example1 expression
cross = Unfold.crossWith (,)

To create a cross product of the streams generated from a tuple we can write:

Example1 expression
:{cross :: Monad m => Unfold m a b -> Unfold m c d -> Unfold m (a, c) (b, d)cross u1 u2 = Unfold.cross (Unfold.lmap fst u1) (Unfold.lmap snd u2):}

Pre-release

valuemkUnfoldM :: (s -> m (Step s b)) -> (a -> m s) -> Unfold m a b
#

Make an unfold from step and inject functions.

Pre-release

valueidentity :: Applicative m => Unfold m a a
#

Identity unfold. The unfold generates a singleton stream having the input as the only element.

identity = function Prelude.id

Pre-release

valuemap2 :: Functor m => (a -> b -> c) -> Unfold m a b -> Unfold m a c
#
Example1 expression
map2 f = Unfold.mapM2 (\a b -> pure (f a b))

Note that the seed may mutate (e.g. if the seed is a Handle or IORef) as stream is generated from it, so we need to be careful when reusing the seed while the stream is being generated from it.

valueboth :: a -> Unfold m a b -> Unfold m Void b
#

Supply the seed to an unfold closing the input end of the unfold.

both a = Unfold.lmap (Prelude.const a)

Pre-release

valuemanyInterleave :: Monad m => Unfold m a b -> Unfold m c a -> Unfold m c b
#

Streamly.Internal.Data.Stream.unfoldManyInterleave for documentation and notes.

This is almost identical to unfoldManyInterleave in StreamD module.

The many combinator is in fact manyAppend to be more explicit in naming.

Internal

valuecrossWithM
  1. :: Monad m
  2. => b -> c -> m d
  3. -> Unfold m a b
  4. -> Unfold m a c
  5. -> Unfold m a d
#

Create a cross product (vector product or cartesian product) of the output streams of two unfolds using a monadic combining function.

Example2 expressions
f1 f u = Unfold.mapM2 (\(_, c) b -> f b c) (Unfold.lmap fst u)crossWithM f u = Unfold.many2 (f1 f u)

Pre-release

Unfolds

0 declarations

Basic Constructors

valuenilM :: Applicative m => (a -> m c) -> Unfold m a b
#

Lift a monadic function into an unfold generating a nil stream with a side effect.

valueconsM :: Applicative m => (a -> m b) -> Unfold m a b -> Unfold m a b
#

Prepend a monadic single element generator function to an Unfold. The same seed is used in the action as well as the unfold.

Pre-release

Generators

Generate a monadic stream from a seed.

valuefromIndicesM :: Applicative m => (Int -> m a) -> Unfold m Int a
#

fromIndicesM gen generates an infinite stream of values using gen starting from the seed.

fromIndicesM f = Unfold.mapM f $ Unfold.enumerateFrom 0

Pre-release

valueiterateM :: Applicative m => (a -> m a) -> Unfold m (m a) a
#

Generates an infinite stream starting with the given seed and applying the given function repeatedly.

Enumerations

classclass Enum a => Enumerable a where
#

Types that can be enumerated as a stream. The operations in this type class are equivalent to those in the Enum type class, except that these generate a stream instead of a list. Use the functions in Streamly.Internal.Data.Unfold.Enumeration module to define new instances.

Pre-release

Methods

  • enumerateFrom :: Monad m => Unfold m a a

    Unfolds from generating a stream starting with the element from, enumerating up to maxBound when the type is Bounded or generating an infinite stream when the type is not Bounded.

    Example1 expression
    Stream.toList $ Stream.take 4 $ Stream.unfold Unfold.enumerateFrom (0 :: Int)[0,1,2,3]

    For Fractional types, enumeration is numerically stable. However, no overflow or underflow checks are performed.

    Example1 expression
    Stream.toList $ Stream.take 4 $ Stream.unfold Unfold.enumerateFrom 1.1[1.1,2.1,3.1,4.1]

    Pre-release

  • enumerateFromTo :: Monad m => Unfold m (a, a) a

    Unfolds (from, to) generating a finite stream starting with the element from, enumerating the type up to the value to. If to is smaller than from then an empty stream is returned.

    Example1 expression
    Stream.toList $ Stream.unfold Unfold.enumerateFromTo (0, 4)[0,1,2,3,4]

    For Fractional types, the last element is equal to the specified to value after rounding to the nearest integral value.

    Example1 expression
    Stream.toList $ Stream.unfold Unfold.enumerateFromTo (1.1, 4)[1.1,2.1,3.1,4.1]
    Example1 expression
    Stream.toList $ Stream.unfold Unfold.enumerateFromTo (1.1, 4.6)[1.1,2.1,3.1,4.1,5.1]

    Pre-release

  • enumerateFromThen :: Monad m => Unfold m (a, a) a

    Unfolds (from, then) generating a stream whose first element is from and the successive elements are in increments of then. Enumeration can occur downwards or upwards depending on whether then comes before or after from. For Bounded types the stream ends when maxBound is reached, for unbounded types it keeps enumerating infinitely.

    Example1 expression
    Stream.toList $ Stream.take 4 $ Stream.unfold Unfold.enumerateFromThen (0, 2)[0,2,4,6]
    Example1 expression
    Stream.toList $ Stream.take 4 $ Stream.unfold Unfold.enumerateFromThen (0,(-2))[0,-2,-4,-6]

    Pre-release

  • enumerateFromThenTo :: Monad m => Unfold m (a, a, a) a

    Unfolds (from, then, to) generating a finite stream whose first element is from and the successive elements are in increments of then up to to. Enumeration can occur downwards or upwards depending on whether then comes before or after from.

    Example1 expression
    Stream.toList $ Stream.unfold Unfold.enumerateFromThenTo (0, 2, 6)[0,2,4,6]
    Example1 expression
    Stream.toList $ Stream.unfold Unfold.enumerateFromThenTo (0, (-2), (-6))[0,-2,-4,-6]

    Pre-release

Instances21Enumerable, …
  • Enumerable IntegerDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable NaturalDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable Int16Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable Int32Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable Int64Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable Int8Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable Word16Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable Word32Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable Word64Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable Word8Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable BoolDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable CharDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable DoubleDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable FloatDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable IntDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable OrderingDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable WordDefined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable ()Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Integral a => Enumerable (Ratio a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • Enumerable a => Enumerable (Identity a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
  • HasResolution a => Enumerable (Fixed a)Defined in streamly-core-0.2.2 · Streamly.Internal.Data.Unfold.Enumeration
valueenumerateFromStepNum :: (Monad m, Num a) => Unfold m (a, a) a
#

Unfolds (from, stride) generating an infinite stream starting from from and incrementing every time by stride. For Bounded types, after the value overflows it keeps enumerating in a cycle:

>>> Stream.toList $ Stream.take 10 $ Stream.unfold Unfold.enumerateFromStepNum (255::Word8,1)
[255,0,1,2,3,4,5,6,7,8]

The implementation is numerically stable for floating point values.

Note enumerateFromStepIntegral is faster for integrals.

Internal

valueenumerateFromNum :: (Monad m, Num a) => Unfold m a a
#

Same as enumerateFromStepNum using a stride of 1:

>>> enumerateFromNum = lmap (from -> (from, 1)) Unfold.enumerateFromStepNum
>>> Stream.toList $ Stream.take 6 $ Stream.unfold enumerateFromNum (0.9)
[0.9,1.9,2.9,3.9,4.9,5.9]

Also, same as enumerateFromThenNum using a stride of 1 but see the note in enumerateFromThenNum about the loss of precision:

>>> enumerateFromNum = lmap (from -> (from, from + 1)) Unfold.enumerateFromThenNum
>>> Stream.toList $ Stream.take 6 $ Stream.unfold enumerateFromNum (0.9)
[0.9,1.9,2.9,3.8999999999999995,4.8999999999999995,5.8999999999999995]

Internal

valueenumerateFromThenNum :: (Monad m, Num a) => Unfold m (a, a) a
#

Same as 'enumerateFromStepNum (from, next)' using a stride of next - from:

>>> enumerateFromThenNum = lmap ((from, next) -> (from, next - from)) Unfold.enumerateFromStepNum

Example: @ >>> Stream.toList $ Stream.take 10 $ Stream.unfold enumerateFromThenNum (255::Word8,0) [255,0,1,2,3,4,5,6,7,8]


The implementation is numerically stable for floating point values.

Note that enumerateFromThenIntegral is faster for integrals.

Note that in the strange world of floating point numbers, using

enumerateFromThenNum (from, from + 1) is almost exactly the same as enumerateFromStepNum (from, 1) but not precisely the same. Because (from + 1) - from is not exactly 1, it may lose some precision, the loss may also be aggregated in each step, if you want that precision then use enumerateFromStepNum instead.

Internal

valueenumerateFromThenToSmall :: (Monad m, Enum a) => Unfold m (a, a, a) a
#

Enumerate from given starting Enum value from and then Enum value next and to Enum value to with stride of (fromEnum next - fromEnum from) till to value.

Internal

From Containers

From Memory

From Stream

Combinators

0 declarations

Mapping on Input

valuediscardFirst :: Unfold m a b -> Unfold m (c, a) b
#

Convert an Unfold into an unfold accepting a tuple as an argument, using the argument of the original fold as the second element of tuple and discarding the first element of the tuple.

discardFirst = Unfold.lmap snd

Pre-release

valuediscardSecond :: Unfold m a b -> Unfold m (a, c) b
#

Convert an Unfold into an unfold accepting a tuple as an argument, using the argument of the original fold as the first element of tuple and discarding the second element of the tuple.

discardSecond = Unfold.lmap fst

Pre-release

valueswap :: Unfold m (a, c) b -> Unfold m (c, a) b
#

Convert an Unfold that accepts a tuple as an argument into an unfold that accepts a tuple with elements swapped.

swap = Unfold.lmap Tuple.swap

Pre-release

Folding

1 declaration
valuefold :: Monad m => Fold m b c -> Unfold m a b -> a -> m c
#

Compose an Unfold and a Fold. Given an Unfold m a b and a Fold m b c, returns a monadic action a -> m c representing the application of the fold on the unfolded stream.

Example1 expression
Unfold.fold Fold.sum Unfold.fromList [1..100]5050
Example1 expression
fold f u = Stream.fold f . Stream.unfold u

Pre-release

Mapping on Output

valuescan :: Monad m => Fold m b c -> Unfold m a b -> Unfold m a c
#

Scan the output of an Unfold to change it in a stateful manner. Once fold is done it will stop.

Example2 expressions
u = Unfold.scan (Fold.take 2 Fold.sum) Unfold.fromListUnfold.fold Fold.toList u [1,2,3,4,5][0,1,3]

Pre-release

valuescanMany :: Monad m => Fold m b c -> Unfold m a b -> Unfold m a c
#

Scan the output of an Unfold to change it in a stateful manner. Once fold is done it will restart from its initial state.

Example2 expressions
u = Unfold.scanMany (Fold.take 2 Fold.sum) Unfold.fromListUnfold.fold Fold.toList u [1,2,3,4,5][0,1,3,0,3,7,0,5]

Pre-release

Either Wrapped Input

Filtering

valuetake :: Applicative m => Int -> Unfold m a b -> Unfold m a b
#
Example2 expressions
u = Unfold.take 2 Unfold.fromListUnfold.fold Fold.toList u [1..100][1,2]
valuedropWhileM :: Monad m => (b -> m Bool) -> Unfold m a b -> Unfold m a b
#

dropWhileM f unf drops elements from the stream generated by unf while the condition holds true. The condition function f is monadic in nature.

Cross product

Resource Management

bracket is the most general resource management operation, all other operations can be expressed using it. These functions have IO suffix because the allocation and cleanup functions are IO actions. For generalized allocation and cleanup functions see the functions without the IO suffix in the "streamly" package.

valuegbracket_
  1. :: Monad m
  2. => (a -> m c)

    before

  3. -> (forall s. m s -> m (Either e s))

    try (exception handling)

  4. -> (c -> m d)

    after, on normal stop

  5. -> Unfold m (c, e) b

    on exception

  6. -> Unfold m c b

    unfold to run

  7. -> Unfold m a b
#

Like gbracketIO but with following differences:

  • alloc action a -> m c runs with async exceptions enabled

  • cleanup action c -> m d won't run if the stream is garbage collected after partial evaluation.

Inhibits stream fusion

Pre-release

valuegbracketIO
  1. :: MonadIO m
  2. => (a -> IO c)

    before

  3. -> (c -> IO d)

    after, on normal stop, or GC

  4. -> (c -> IO ())

    action on exception

  5. -> Unfold m e b

    stream on exception

  6. -> (forall s. m s -> IO (Either e s))

    try (exception handling)

  7. -> Unfold m c b

    unfold to run

  8. -> Unfold m a b
#

Run the alloc action a -> m c with async exceptions disabled but keeping blocking operations interruptible (see mask). Use the output c as input to Unfold m c b to generate an output stream. When unfolding use the supplied try operation forall s. m s -> m (Either e s) to catch synchronous exceptions. If an exception occurs run the exception handling unfold Unfold m (c, e) b.

The cleanup action c -> m d, runs whenever the stream ends normally, due to a sync or async exception or if it gets garbage collected after a partial lazy evaluation. See bracket for the semantics of the cleanup action.

gbracket can express all other exception handling combinators.

Inhibits stream fusion

Pre-release

valuebefore :: (a -> m c) -> Unfold m a b -> Unfold m a b
#

Run a side effect a -> m c on the input a before unfolding it using Unfold m a b.

before f = lmapM (\a -> f a >> return a)

Pre-release

valueafterIO :: MonadIO m => (a -> IO c) -> Unfold m a b -> Unfold m a b
#

Unfold the input a using Unfold m a b, run an action on a whenever the unfold stops normally, or if it is garbage collected after a partial lazy evaluation.

The semantics of the action a -> m c are similar to the cleanup action semantics in bracket.

See also after_

Pre-release

valueafter_ :: Monad m => (a -> m c) -> Unfold m a b -> Unfold m a b
#

Like after with following differences:

  • action a -> m c won't run if the stream is garbage collected after partial evaluation.

  • Monad m does not require any other constraints.

Pre-release

valuefinallyIO
  1. :: (MonadIO m, MonadCatch m)
  2. => a -> IO c
  3. -> Unfold m a b
  4. -> Unfold m a b
#

Unfold the input a using Unfold m a b, run an action on a whenever the unfold stops normally, aborts due to an exception or if it is garbage collected after a partial lazy evaluation.

The semantics of the action a -> m c are similar to the cleanup action semantics in bracket.

finally release = bracket return release

See also finally_

Inhibits stream fusion

Pre-release

valuefinally_ :: MonadCatch m => (a -> m c) -> Unfold m a b -> Unfold m a b
#

Like finallyIO with following differences:

  • action a -> m c won't run if the stream is garbage collected after partial evaluation.

Inhibits stream fusion

Pre-release

valuebracketIO
  1. :: (MonadIO m, MonadCatch m)
  2. => a -> IO c
  3. -> c -> IO d
  4. -> Unfold m c b
  5. -> Unfold m a b
#

Run the alloc action a -> m c with async exceptions disabled but keeping blocking operations interruptible (see mask). Use the output c as input to Unfold m c b to generate an output stream.

c is usually a resource under the state of monad m, e.g. a file handle, that requires a cleanup after use. The cleanup action c -> m d, runs whenever the stream ends normally, due to a sync or async exception or if it gets garbage collected after a partial lazy evaluation.

bracket only guarantees that the cleanup action runs, and it runs with async exceptions enabled. The action must ensure that it can successfully cleanup the resource in the face of sync or async exceptions.

When the stream ends normally or on a sync exception, cleanup action runs immediately in the current thread context, whereas in other cases it runs in the GC context, therefore, cleanup may be delayed until the GC gets to run.

See also: bracket_, gbracket

Inhibits stream fusion

Pre-release

valuebracket_
  1. :: MonadCatch m
  2. => a -> m c
  3. -> c -> m d
  4. -> Unfold m c b
  5. -> Unfold m a b
#

Like bracketIO but with following differences:

  • alloc action a -> m c runs with async exceptions enabled

  • cleanup action c -> m d won't run if the stream is garbage collected after partial evaluation.

Inhibits stream fusion

Pre-release

Exceptions

Most of these combinators inhibit stream fusion, therefore, when possible, they should be called in an outer loop to mitigate the cost. For example, instead of calling them on a stream of chars call them on a stream of arrays before flattening it to a stream of chars.

valueonException :: MonadCatch m => (a -> m c) -> Unfold m a b -> Unfold m a b
#

Unfold the input a using Unfold m a b, run the action a -> m c on a if the unfold aborts due to an exception.

Inhibits stream fusion

Pre-release