-- |
-- Module      : Streamly.Internal.Data.Scanr
-- Copyright   : (c) 2019 Composewell Technologies
-- License     : BSD3
-- Maintainer  : streamly@composewell.com
-- Stability   : experimental
-- Portability : GHC
--
-- Right scans.
--
-- == Scanr vs Stream
--
-- A scan is a generalization of a stream. Like streams, a scan has an internal
-- state. Unlike a stream, a scan produces an output only on an input, the
-- output is a function of the scan state and the input. A scan produces at
-- most one output on one input, in other words it is driven solely by the
-- input, it cannot produce output on its own. A @Scanr m () a@ can represent a
-- @Stream m a@ by supplying the scan with () inputs.
--
-- == Scans vs pipes:
--
-- A scan is a simpler version of pipes. It can produce at most one output on
-- one input. Whereas a pipe may produce output even without consuming anything
-- or it can produce multiple outputs on a single input. Scans are simpler
-- abstractions to think about compared to pipes and easier for the compiler to
-- optimize and fuse.
--
-- == Compositions
--
-- Append: this is the easiest. The behavior is simple even in presence of
-- filtering (Skip) and termination (Stop). Skip translates to Skip, Stop
-- translates to Stop.
--
-- demux: we select one of n scans to run. Behaviour with Skip is straight
-- forward. Termination behavior has multiple options, stop when first one
-- stops, stop when the last one stops, or stop when a selected one stops.
--
-- zip: run all and zip the outputs. If one of them Skips we Skip the output.
-- If one of them stops we stop. It may be possible to collect the outputs as
-- Just/Nothing values.
--
-- Another option could be if a Scan terminates do we want to start it again or
-- not.

module Streamly.Internal.Data.Scanr
    (
    -- * Type
      Scanr (..)

    -- * Primitive Scans
    , identity
    , function
    , functionM
    , filter
    , filterM

    -- * Combinators
    , compose
    , teeWithMay
    , teeWith
    , tee

    -- * Scans
    , length
    , sum
    )
where

#include "inline.hs"
import Control.Arrow (Arrow(..))
import Control.Category (Category(..))
import Data.Maybe (isJust, fromJust)
import Fusion.Plugin.Types (Fuse(..))
import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
import Streamly.Internal.Data.Stream.Step (Step (..))

import qualified Prelude

import Prelude hiding
    (filter, length, sum, zipWith, map, mapM, id, unzip, null)

-- $setup
-- >>> :m
-- >>> :set -XFlexibleContexts
-- >>> import Control.Category
--
-- >>> import qualified Streamly.Internal.Data.Fold as Fold
-- >>> import qualified Streamly.Internal.Data.Scanr as Scanr
-- >>> import qualified Streamly.Internal.Data.Stream as Stream

------------------------------------------------------------------------------
-- Scans
------------------------------------------------------------------------------

-- A core difference between the Scan type and the Fold type is that Scan can
-- stop without producing an output, this is required to represent an empty
-- stream. For this reason a Scan cannot be represented using a Fold because a
-- fold requires a value to be produced on Stop.

-- A core difference between a Scan and a Stream is that a scan produces an
-- output only on an input while a stream can produce output without consuming
-- an input.
--
-- XXX A scan may have buffered data which may have to be drained if the driver
-- has no more input to supply. So we need a finalizer which produces a
-- (possibly empty) stream.
--
-- XXX We should add finalizer (and Error constructor?) to it before we
-- release it.

-- | Represents a stateful transformation over an input stream of values of
-- type @a@ to outputs of type @b@ in 'Monad' @m@.
--
-- The constructor is @Scan consume initial@.
data Scanr m a b =
    forall s. Scanr
        (s -> a -> m (Step s b))
        s

------------------------------------------------------------------------------
-- Functor: Mapping on the output
------------------------------------------------------------------------------

-- | 'fmap' maps a pure function on a scan output.
--
-- >>> Stream.toList $ Stream.scanr (fmap (+1) Scanr.identity) $ Stream.fromList [1..5::Int]
-- [2,3,4,5,6]
--
instance Functor m => Functor (Scanr m a) where
    {-# INLINE_NORMAL fmap #-}
    fmap :: forall a b. (a -> b) -> Scanr m a a -> Scanr m a b
fmap a -> b
f (Scanr s -> a -> m (Step s a)
consume s
initial) = (s -> a -> m (Step s b)) -> s -> Scanr m a b
forall (m :: * -> *) a b s.
(s -> a -> m (Step s b)) -> s -> Scanr m a b
Scanr s -> a -> m (Step s b)
consume1 s
initial

        where

        {-# INLINE_LATE consume1 #-}
        consume1 :: s -> a -> m (Step s b)
consume1 s
s a
b = (Step s a -> Step s b) -> m (Step s a) -> m (Step s 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) -> Step s a -> Step s b
forall a b. (a -> b) -> Step s a -> Step s b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f) (s -> a -> m (Step s a)
consume s
s a
b)

-------------------------------------------------------------------------------
-- Category
-------------------------------------------------------------------------------

-- XXX We can call this append, because corresponding operation in stream is
-- also append.

-- | Connect two scans in series. Attach the first scan on the output of the
-- second scan.
--
-- >>> import Control.Category
-- >>> Stream.toList $ Stream.scanr (Scanr.function (+1) >>> Scanr.function (+1)) $ Stream.fromList [1..5::Int]
-- [3,4,5,6,7]
--
{-# INLINE_NORMAL compose #-}
compose :: Monad m => Scanr m b c -> Scanr m a b -> Scanr m a c
compose :: forall (m :: * -> *) b c a.
Monad m =>
Scanr m b c -> Scanr m a b -> Scanr m a c
compose
    (Scanr s -> b -> m (Step s c)
stepR s
initialR)
    (Scanr s -> a -> m (Step s b)
stepL s
initialL) = ((s, s) -> a -> m (Step (s, s) c)) -> (s, s) -> Scanr m a c
forall (m :: * -> *) a b s.
(s -> a -> m (Step s b)) -> s -> Scanr m a b
Scanr (s, s) -> a -> m (Step (s, s) c)
step (s
initialL, s
initialR)

    where

    -- XXX Use strict tuple?
    step :: (s, s) -> a -> m (Step (s, s) c)
step (s
sL, s
sR) a
x = do
        Step s b
rL <- s -> a -> m (Step s b)
stepL s
sL a
x
        case Step s b
rL of
            Yield b
bL s
sL1 -> do
                Step s c
rR <- s -> b -> m (Step s c)
stepR s
sR b
bL
                Step (s, s) c -> m (Step (s, s) c)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
                    (Step (s, s) c -> m (Step (s, s) c))
-> Step (s, s) c -> m (Step (s, s) c)
forall a b. (a -> b) -> a -> b
$ case Step s c
rR of
                        Yield c
br s
sR1 -> c -> (s, s) -> Step (s, s) c
forall s a. a -> s -> Step s a
Yield c
br (s
sL1, s
sR1)
                        Skip s
sR1 -> (s, s) -> Step (s, s) c
forall s a. s -> Step s a
Skip (s
sL1, s
sR1)
                        Step s c
Stop -> Step (s, s) c
forall s a. Step s a
Stop
            Skip s
sL1 -> Step (s, s) c -> m (Step (s, s) c)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step (s, s) c -> m (Step (s, s) c))
-> Step (s, s) c -> m (Step (s, s) c)
forall a b. (a -> b) -> a -> b
$ (s, s) -> Step (s, s) c
forall s a. s -> Step s a
Skip (s
sL1, s
sR)
            Step s b
Stop -> Step (s, s) c -> m (Step (s, s) c)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Step (s, s) c
forall s a. Step s a
Stop

-- | A scan representing mapping of a monadic action.
--
-- >>> Stream.toList $ Stream.scanr (Scanr.functionM print) $ Stream.fromList [1..5::Int]
-- 1
-- 2
-- 3
-- 4
-- 5
-- [(),(),(),(),()]
--
{-# INLINE functionM #-}
functionM :: Monad m => (a -> m b) -> Scanr m a b
functionM :: forall (m :: * -> *) a b. Monad m => (a -> m b) -> Scanr m a b
functionM a -> m b
f = (() -> a -> m (Step () b)) -> () -> Scanr m a b
forall (m :: * -> *) a b s.
(s -> a -> m (Step s b)) -> s -> Scanr m a b
Scanr (\() a
a -> (b -> Step () b) -> m b -> m (Step () b)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (b -> () -> Step () b
forall s a. a -> s -> Step s a
`Yield` ()) (a -> m b
f a
a)) ()

-- | A scan representing mapping of a pure function.
--
-- >>> Stream.toList $ Stream.scanr (Scanr.function (+1)) $ Stream.fromList [1..5::Int]
-- [2,3,4,5,6]
--
{-# INLINE function #-}
function :: Monad m => (a -> b) -> Scanr m a b
function :: forall (m :: * -> *) a b. Monad m => (a -> b) -> Scanr m a b
function a -> b
f = (a -> m b) -> Scanr m a b
forall (m :: * -> *) a b. Monad m => (a -> m b) -> Scanr m a b
functionM (b -> m b
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> m b) -> (a -> b) -> a -> m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
Prelude.. a -> b
f)

{- HLINT ignore "Redundant map" -}

-- | An identity scan producing the same output as input.
--
-- >>> identity = Scanr.function Prelude.id
--
-- >>> Stream.toList $ Stream.scanr (Scanr.identity) $ Stream.fromList [1..5::Int]
-- [1,2,3,4,5]
--
{-# INLINE identity #-}
identity :: Monad m => Scanr m a a
identity :: forall (m :: * -> *) a. Monad m => Scanr m a a
identity = (a -> a) -> Scanr m a a
forall (m :: * -> *) a b. Monad m => (a -> b) -> Scanr m a b
function a -> a
forall a. a -> a
Prelude.id

instance Monad m => Category (Scanr m) where
    {-# INLINE id #-}
    id :: forall a. Scanr m a a
id = Scanr m a a
forall (m :: * -> *) a. Monad m => Scanr m a a
identity

    {-# INLINE (.) #-}
    . :: forall b c a. Scanr m b c -> Scanr m a b -> Scanr m a c
(.) = Scanr m b c -> Scanr m a b -> Scanr m a c
forall (m :: * -> *) b c a.
Monad m =>
Scanr m b c -> Scanr m a b -> Scanr m a c
compose

-------------------------------------------------------------------------------
-- Applicative Zip
-------------------------------------------------------------------------------

{-# ANN type TeeWith Fuse #-}
data TeeWith sL sR = TeeWith !sL !sR

-- XXX zipWith?

-- | Connect two scans in parallel. Distribute the input across two scans and
-- zip their outputs. If the scan filters the output, 'Nothing' is emitted
-- otherwise 'Just' is emitted. The scan stops if any of the scans stop.
--
-- >>> Stream.toList $ Stream.scanr (Scanr.teeWithMay (,) Scanr.identity (Scanr.function (\x -> x * x))) $ Stream.fromList [1..5::Int]
-- [(Just 1,Just 1),(Just 2,Just 4),(Just 3,Just 9),(Just 4,Just 16),(Just 5,Just 25)]
--
{-# INLINE_NORMAL teeWithMay #-}
teeWithMay :: Monad m =>
    (Maybe b -> Maybe c -> d) -> Scanr m a b -> Scanr m a c -> Scanr m a d
teeWithMay :: forall (m :: * -> *) b c d a.
Monad m =>
(Maybe b -> Maybe c -> d)
-> Scanr m a b -> Scanr m a c -> Scanr m a d
teeWithMay Maybe b -> Maybe c -> d
f (Scanr s -> a -> m (Step s b)
stepL s
initialL) (Scanr s -> a -> m (Step s c)
stepR s
initialR) =
    (TeeWith s s -> a -> m (Step (TeeWith s s) d))
-> TeeWith s s -> Scanr m a d
forall (m :: * -> *) a b s.
(s -> a -> m (Step s b)) -> s -> Scanr m a b
Scanr TeeWith s s -> a -> m (Step (TeeWith s s) d)
step (s -> s -> TeeWith s s
forall sL sR. sL -> sR -> TeeWith sL sR
TeeWith s
initialL s
initialR)

    where

    step :: TeeWith s s -> a -> m (Step (TeeWith s s) d)
step (TeeWith s
sL s
sR) a
a = do
        Step s b
resL <- s -> a -> m (Step s b)
stepL s
sL a
a
        Step s c
resR <- s -> a -> m (Step s c)
stepR s
sR a
a
        Step (TeeWith s s) d -> m (Step (TeeWith s s) d)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
            (Step (TeeWith s s) d -> m (Step (TeeWith s s) d))
-> Step (TeeWith s s) d -> m (Step (TeeWith s s) d)
forall a b. (a -> b) -> a -> b
$ case Step s b
resL of
                  Yield b
bL s
sL1 ->
                    case Step s c
resR of
                        Yield c
bR s
sR1 ->
                            d -> TeeWith s s -> Step (TeeWith s s) d
forall s a. a -> s -> Step s a
Yield
                                (Maybe b -> Maybe c -> d
f (b -> Maybe b
forall a. a -> Maybe a
Just b
bL) (c -> Maybe c
forall a. a -> Maybe a
Just c
bR))
                                (s -> s -> TeeWith s s
forall sL sR. sL -> sR -> TeeWith sL sR
TeeWith s
sL1 s
sR1)
                        Skip s
sR1 ->
                            d -> TeeWith s s -> Step (TeeWith s s) d
forall s a. a -> s -> Step s a
Yield
                                (Maybe b -> Maybe c -> d
f (b -> Maybe b
forall a. a -> Maybe a
Just b
bL) Maybe c
forall a. Maybe a
Nothing)
                                (s -> s -> TeeWith s s
forall sL sR. sL -> sR -> TeeWith sL sR
TeeWith s
sL1 s
sR1)
                        Step s c
Stop -> Step (TeeWith s s) d
forall s a. Step s a
Stop
                  Skip s
sL1 ->
                    case Step s c
resR of
                        Yield c
bR s
sR1 ->
                            d -> TeeWith s s -> Step (TeeWith s s) d
forall s a. a -> s -> Step s a
Yield
                                (Maybe b -> Maybe c -> d
f Maybe b
forall a. Maybe a
Nothing (c -> Maybe c
forall a. a -> Maybe a
Just c
bR))
                                (s -> s -> TeeWith s s
forall sL sR. sL -> sR -> TeeWith sL sR
TeeWith s
sL1 s
sR1)
                        Skip s
sR1 ->
                            d -> TeeWith s s -> Step (TeeWith s s) d
forall s a. a -> s -> Step s a
Yield
                                (Maybe b -> Maybe c -> d
f Maybe b
forall a. Maybe a
Nothing Maybe c
forall a. Maybe a
Nothing)
                                (s -> s -> TeeWith s s
forall sL sR. sL -> sR -> TeeWith sL sR
TeeWith s
sL1 s
sR1)
                        Step s c
Stop -> Step (TeeWith s s) d
forall s a. Step s a
Stop
                  Step s b
Stop -> Step (TeeWith s s) d
forall s a. Step s a
Stop

-- | Produces an output only when both the scans produce an output. If any of
-- the scans skips the output then the composed scan also skips. Stops when any
-- of the scans stop.
--
-- >>> Stream.toList $ Stream.scanr (Scanr.teeWith (,) Scanr.identity (Scanr.function (\x -> x * x))) $ Stream.fromList [1..5::Int]
-- [(1,1),(2,4),(3,9),(4,16),(5,25)]
--
{-# INLINE_NORMAL teeWith #-}
teeWith :: Monad m =>
    (b -> c -> d) -> Scanr m a b -> Scanr m a c -> Scanr m a d
teeWith :: forall (m :: * -> *) b c d a.
Monad m =>
(b -> c -> d) -> Scanr m a b -> Scanr m a c -> Scanr m a d
teeWith b -> c -> d
f Scanr m a b
s1 Scanr m a c
s2 =
    (Maybe d -> d) -> Scanr m a (Maybe d) -> Scanr m a d
forall a b. (a -> b) -> Scanr m a a -> Scanr m a b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe d -> d
forall a. HasCallStack => Maybe a -> a
fromJust
        (Scanr m a (Maybe d) -> Scanr m a d)
-> Scanr m a (Maybe d) -> Scanr m a d
forall a b. (a -> b) -> a -> b
$ Scanr m (Maybe d) (Maybe d)
-> Scanr m a (Maybe d) -> Scanr m a (Maybe d)
forall (m :: * -> *) b c a.
Monad m =>
Scanr m b c -> Scanr m a b -> Scanr m a c
compose ((Maybe d -> Bool) -> Scanr m (Maybe d) (Maybe d)
forall (m :: * -> *) a. Monad m => (a -> Bool) -> Scanr m a a
filter Maybe d -> Bool
forall a. Maybe a -> Bool
isJust)
        (Scanr m a (Maybe d) -> Scanr m a (Maybe d))
-> Scanr m a (Maybe d) -> Scanr m a (Maybe d)
forall a b. (a -> b) -> a -> b
$ (Maybe b -> Maybe c -> Maybe d)
-> Scanr m a b -> Scanr m a c -> Scanr m a (Maybe d)
forall (m :: * -> *) b c d a.
Monad m =>
(Maybe b -> Maybe c -> d)
-> Scanr m a b -> Scanr m a c -> Scanr m a d
teeWithMay (\Maybe b
b Maybe c
c -> b -> c -> d
f (b -> c -> d) -> Maybe b -> Maybe (c -> d)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe b
b Maybe (c -> d) -> Maybe c -> Maybe d
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe c
c) Scanr m a b
s1 Scanr m a c
s2

-- | Zips the outputs only when both scans produce outputs, discards otherwise.
instance Monad m => Applicative (Scanr m a) where
    {-# INLINE pure #-}
    pure :: forall a. a -> Scanr m a a
pure a
b = (() -> a -> m (Step () a)) -> () -> Scanr m a a
forall (m :: * -> *) a b s.
(s -> a -> m (Step s b)) -> s -> Scanr m a b
Scanr (\()
_ a
_ -> Step () a -> m (Step () a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Step () a -> m (Step () a)) -> Step () a -> m (Step () a)
forall a b. (a -> b) -> a -> b
$ a -> () -> Step () a
forall s a. a -> s -> Step s a
Yield a
b ()) ()

    <*> :: forall a b. Scanr m a (a -> b) -> Scanr m a a -> Scanr m a b
(<*>) = ((a -> b) -> a -> b)
-> Scanr m a (a -> b) -> Scanr m a a -> Scanr m a b
forall (m :: * -> *) b c d a.
Monad m =>
(b -> c -> d) -> Scanr m a b -> Scanr m a c -> Scanr m a d
teeWith (a -> b) -> a -> b
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id

{-# INLINE_NORMAL tee #-}
tee :: Monad m => Scanr m a b -> Scanr m a c -> Scanr m a (b,c)
tee :: forall (m :: * -> *) a b c.
Monad m =>
Scanr m a b -> Scanr m a c -> Scanr m a (b, c)
tee = (b -> c -> (b, c))
-> Scanr m a b -> Scanr m a c -> Scanr m a (b, c)
forall (m :: * -> *) b c d a.
Monad m =>
(b -> c -> d) -> Scanr m a b -> Scanr m a c -> Scanr m a d
teeWith (,)

-------------------------------------------------------------------------------
-- Arrow
-------------------------------------------------------------------------------

-- | Use the first scan for the first element of the tuple and second scan for
-- the second. Zip the outputs. Emits 'Nothing' if no output is generated by
-- the scan, otherwise emits 'Just'. Stops as soon as any one of the scans
-- stop.
--
{-# INLINE_NORMAL unzipMay #-}
unzipMay :: Monad m =>
    Scanr m a x -> Scanr m b y -> Scanr m (a, b) (Maybe x, Maybe y)
unzipMay :: forall (m :: * -> *) a x b y.
Monad m =>
Scanr m a x -> Scanr m b y -> Scanr m (a, b) (Maybe x, Maybe y)
unzipMay (Scanr s -> a -> m (Step s x)
stepL s
initialL) (Scanr s -> b -> m (Step s y)
stepR s
initialR) =
    (Tuple' s s -> (a, b) -> m (Step (Tuple' s s) (Maybe x, Maybe y)))
-> Tuple' s s -> Scanr m (a, b) (Maybe x, Maybe y)
forall (m :: * -> *) a b s.
(s -> a -> m (Step s b)) -> s -> Scanr m a b
Scanr Tuple' s s -> (a, b) -> m (Step (Tuple' s s) (Maybe x, Maybe y))
step (s -> s -> Tuple' s s
forall a b. a -> b -> Tuple' a b
Tuple' s
initialL s
initialR)

    where

    step :: Tuple' s s -> (a, b) -> m (Step (Tuple' s s) (Maybe x, Maybe y))
step (Tuple' s
sL s
sR) (a
a, b
b) = do
        Step s x
resL <- s -> a -> m (Step s x)
stepL s
sL a
a
        Step s y
resR <- s -> b -> m (Step s y)
stepR s
sR b
b
        Step (Tuple' s s) (Maybe x, Maybe y)
-> m (Step (Tuple' s s) (Maybe x, Maybe y))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
            (Step (Tuple' s s) (Maybe x, Maybe y)
 -> m (Step (Tuple' s s) (Maybe x, Maybe y)))
-> Step (Tuple' s s) (Maybe x, Maybe y)
-> m (Step (Tuple' s s) (Maybe x, Maybe y))
forall a b. (a -> b) -> a -> b
$ case Step s x
resL of
                  Yield x
bL s
sL1 ->
                    case Step s y
resR of
                        Yield y
bR s
sR1 ->
                            (Maybe x, Maybe y)
-> Tuple' s s -> Step (Tuple' s s) (Maybe x, Maybe y)
forall s a. a -> s -> Step s a
Yield
                                (x -> Maybe x
forall a. a -> Maybe a
Just x
bL, y -> Maybe y
forall a. a -> Maybe a
Just y
bR)
                                (s -> s -> Tuple' s s
forall a b. a -> b -> Tuple' a b
Tuple' s
sL1 s
sR1)
                        Skip s
sR1 ->
                            (Maybe x, Maybe y)
-> Tuple' s s -> Step (Tuple' s s) (Maybe x, Maybe y)
forall s a. a -> s -> Step s a
Yield
                                (x -> Maybe x
forall a. a -> Maybe a
Just x
bL, Maybe y
forall a. Maybe a
Nothing)
                                (s -> s -> Tuple' s s
forall a b. a -> b -> Tuple' a b
Tuple' s
sL1 s
sR1)
                        Step s y
Stop -> Step (Tuple' s s) (Maybe x, Maybe y)
forall s a. Step s a
Stop
                  Skip s
sL1 ->
                    case Step s y
resR of
                        Yield y
bR s
sR1 ->
                            (Maybe x, Maybe y)
-> Tuple' s s -> Step (Tuple' s s) (Maybe x, Maybe y)
forall s a. a -> s -> Step s a
Yield
                                (Maybe x
forall a. Maybe a
Nothing, y -> Maybe y
forall a. a -> Maybe a
Just y
bR)
                                (s -> s -> Tuple' s s
forall a b. a -> b -> Tuple' a b
Tuple' s
sL1 s
sR1)
                        Skip s
sR1 ->
                            (Maybe x, Maybe y)
-> Tuple' s s -> Step (Tuple' s s) (Maybe x, Maybe y)
forall s a. a -> s -> Step s a
Yield
                                (Maybe x
forall a. Maybe a
Nothing, Maybe y
forall a. Maybe a
Nothing)
                                (s -> s -> Tuple' s s
forall a b. a -> b -> Tuple' a b
Tuple' s
sL1 s
sR1)
                        Step s y
Stop -> Step (Tuple' s s) (Maybe x, Maybe y)
forall s a. Step s a
Stop
                  Step s x
Stop -> Step (Tuple' s s) (Maybe x, Maybe y)
forall s a. Step s a
Stop

-- | Like 'unzipMay' but produces an output only when both the scans produce an
-- output. Other outputs are filtered out.
{-# INLINE_NORMAL unzip #-}
unzip :: Monad m => Scanr m a x -> Scanr m b y -> Scanr m (a, b) (x, y)
unzip :: forall (m :: * -> *) a x b y.
Monad m =>
Scanr m a x -> Scanr m b y -> Scanr m (a, b) (x, y)
unzip Scanr m a x
s1 Scanr m b y
s2 = ((Maybe x, Maybe y) -> (x, y))
-> Scanr m (a, b) (Maybe x, Maybe y) -> Scanr m (a, b) (x, y)
forall a b. (a -> b) -> Scanr m (a, b) a -> Scanr m (a, b) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Maybe (x, y) -> (x, y)
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (x, y) -> (x, y))
-> ((Maybe x, Maybe y) -> Maybe (x, y))
-> (Maybe x, Maybe y)
-> (x, y)
forall b c a. (b -> c) -> (a -> b) -> a -> c
Prelude.. (Maybe x, Maybe y) -> Maybe (x, y)
forall {a} {b}. (Maybe a, Maybe b) -> Maybe (a, b)
f) (Scanr m (a, b) (Maybe x, Maybe y) -> Scanr m (a, b) (x, y))
-> Scanr m (a, b) (Maybe x, Maybe y) -> Scanr m (a, b) (x, y)
forall a b. (a -> b) -> a -> b
$ Scanr m a x -> Scanr m b y -> Scanr m (a, b) (Maybe x, Maybe y)
forall (m :: * -> *) a x b y.
Monad m =>
Scanr m a x -> Scanr m b y -> Scanr m (a, b) (Maybe x, Maybe y)
unzipMay Scanr m a x
s1 Scanr m b y
s2

    where

    f :: (Maybe a, Maybe b) -> Maybe (a, b)
f (Maybe a
mx, Maybe b
my) =
        case Maybe a
mx of
            Just a
x ->
                case Maybe b
my of
                    Just b
y -> (a, b) -> Maybe (a, b)
forall a. a -> Maybe a
Just (a
x, b
y)
                    Maybe b
Nothing -> Maybe (a, b)
forall a. Maybe a
Nothing
            Maybe a
Nothing -> Maybe (a, b)
forall a. Maybe a
Nothing

instance Monad m => Arrow (Scanr m) where
    {-# INLINE arr #-}
    arr :: forall b c. (b -> c) -> Scanr m b c
arr = (b -> c) -> Scanr m b c
forall (m :: * -> *) a b. Monad m => (a -> b) -> Scanr m a b
function

    {-# INLINE (***) #-}
    *** :: forall b c b' c'.
Scanr m b c -> Scanr m b' c' -> Scanr m (b, b') (c, c')
(***) = Scanr m b c -> Scanr m b' c' -> Scanr m (b, b') (c, c')
forall (m :: * -> *) a x b y.
Monad m =>
Scanr m a x -> Scanr m b y -> Scanr m (a, b) (x, y)
unzip

    {-# INLINE (&&&) #-}
    &&& :: forall b c c'. Scanr m b c -> Scanr m b c' -> Scanr m b (c, c')
(&&&) = (c -> c' -> (c, c'))
-> Scanr m b c -> Scanr m b c' -> Scanr m b (c, c')
forall (m :: * -> *) b c d a.
Monad m =>
(b -> c -> d) -> Scanr m a b -> Scanr m a c -> Scanr m a d
teeWith (,)

-------------------------------------------------------------------------------
-- Primitive scans
-------------------------------------------------------------------------------

-- | A filtering scan using a monadic predicate.
{-# INLINE filterM #-}
filterM :: Monad m => (a -> m Bool) -> Scanr m a a
filterM :: forall (m :: * -> *) a. Monad m => (a -> m Bool) -> Scanr m a a
filterM a -> m Bool
f = (() -> a -> m (Step () a)) -> () -> Scanr m a a
forall (m :: * -> *) a b s.
(s -> a -> m (Step s b)) -> s -> Scanr m a b
Scanr (\() a
a -> a -> m Bool
f a
a m Bool -> (Bool -> m (Step () a)) -> m (Step () a)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> Bool -> m (Step () a)
forall {m :: * -> *} {a}. Monad m => a -> Bool -> m (Step () a)
g a
a) ()

    where

    {-# INLINE g #-}
    g :: a -> Bool -> m (Step () a)
g a
a Bool
b =
        Step () a -> m (Step () a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
            (Step () a -> m (Step () a)) -> Step () a -> m (Step () a)
forall a b. (a -> b) -> a -> b
$ if Bool
b
              then a -> () -> Step () a
forall s a. a -> s -> Step s a
Yield a
a ()
              else () -> Step () a
forall s a. s -> Step s a
Skip ()

-- | A filtering scan using a pure predicate.
--
-- >>> Stream.toList $ Stream.scanr (Scanr.filter odd) $ Stream.fromList [1..5::Int]
-- [1,3,5]
--
{-# INLINE filter #-}
filter :: Monad m => (a -> Bool) -> Scanr m a a
filter :: forall (m :: * -> *) a. Monad m => (a -> Bool) -> Scanr m a a
filter a -> Bool
f = (a -> m Bool) -> Scanr m a a
forall (m :: * -> *) a. Monad m => (a -> m Bool) -> Scanr m a a
filterM (Bool -> m Bool
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> m Bool) -> (a -> Bool) -> a -> m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
Prelude.. a -> Bool
f)

{-# INLINE length #-}
length :: Monad m => Scanr m a Int
length :: forall (m :: * -> *) a. Monad m => Scanr m a Int
length = (Int -> a -> m (Step Int Int)) -> Int -> Scanr m a Int
forall (m :: * -> *) a b s.
(s -> a -> m (Step s b)) -> s -> Scanr m a b
Scanr (\Int
acc a
_ -> Step Int Int -> m (Step Int Int)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Step Int Int -> m (Step Int Int))
-> Step Int Int -> m (Step Int Int)
forall a b. (a -> b) -> a -> b
$ let !n :: Int
n = Int
acc Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 in Int -> Int -> Step Int Int
forall s a. a -> s -> Step s a
Yield Int
n Int
n) Int
0

{-# INLINE sum #-}
sum :: (Monad m, Num a) => Scanr m a a
sum :: forall (m :: * -> *) a. (Monad m, Num a) => Scanr m a a
sum = (a -> a -> m (Step a a)) -> a -> Scanr m a a
forall (m :: * -> *) a b s.
(s -> a -> m (Step s b)) -> s -> Scanr m a b
Scanr (\a
acc a
x -> Step a a -> m (Step a a)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Step a a -> m (Step a a)) -> Step a a -> m (Step a a)
forall a b. (a -> b) -> a -> b
$ let !n :: a
n = a
acc a -> a -> a
forall a. Num a => a -> a -> a
+ a
x in a -> a -> Step a a
forall s a. a -> s -> Step s a
Yield a
n a
n) a
0