{-# LANGUAGE BangPatterns              #-}
{-# LANGUAGE CPP                       #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts          #-}
{-# LANGUAGE PatternSynonyms           #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}

#include "inline.hs"

-- |
-- Module      : Streamly.Data.Unfold
-- Copyright   : (c) 2019 Composewell Technologies
-- License     : BSD3
-- Maintainer  : streamly@composewell.com
-- Stability   : experimental
-- Portability : GHC
--
-- 'Unfold' type represents an effectful action that generates a stream of
-- values from a single starting value often called a seed value. Values can be
-- generated and /pulled/ from the 'Unfold' one at a time. It can also be
-- called a producer or a source of stream.  It is a data representation of the
-- standard 'S.unfoldr' function.  An 'Unfold' can be converted into a stream
-- type using 'S.unfold' by supplying the seed.
--
-- = Performance Notes
--
-- 'Unfold' representation is more efficient than using streams when combining
-- streams.  'Unfold' type allows multiple unfold actions to be composed into a
-- single unfold function in an efficient manner by enabling the compiler to
-- perform stream fusion optimization.
-- @Unfold m a b@ can be considered roughly equivalent to an action @a -> t m
-- b@ (where @t@ is a stream type). Instead of using an 'Unfold' one could just
-- use a function of the shape @a -> t m b@. However, working with stream types
-- like 'S.SerialT' does not allow the compiler to perform stream fusion
-- optimization when merging, appending or concatenating multiple streams.
-- Even though stream based combinator have excellent performance, they are
-- much less efficient when compared to combinators using 'Unfold'.  For
-- example, the 'S.concatMap' combinator which uses @a -> t m b@ (where @t@ is
-- a stream type) to generate streams is much less efficient compared to
-- 'S.concatUnfold'.
--
-- On the other hand, transformation operations on stream types are as
-- efficient as transformations on 'Unfold'.
--
-- We should note that in some cases working with stream types may be more
-- convenient compared to working with the 'Unfold' type.  However, if extra
-- performance boost is important then 'Unfold' based composition should be
-- preferred compared to stream based composition when merging or concatenating
-- streams.
--
-- = Programmer Notes
--
-- > import qualified Streamly.Data.Unfold as UF
--
-- More, not yet exposed, unfold combinators can be found in
-- "Streamly.Internal.Data.Unfold".

-- The stream types (e.g. 'S.SerialT') can be considered as a special case of
-- 'Unfold' with no starting seed.
--
module Streamly.Data.Unfold
    (
    -- * Unfold Type
      Unfold
    )
where

import Prelude hiding (concat, map, takeWhile, take, filter, const)
import Streamly.Internal.Data.Unfold