{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}

{- | An optimization layer on "Data.Stream".

Since both variants are semantically the same, not the full API of "Data.Stream" is replicated here.
-}
module Data.Stream.Optimized where

-- base
import Control.Applicative (Alternative (..), Applicative (..), liftA2)
import Data.Monoid (Ap (..))
import Prelude hiding (Applicative (..))

-- transformers
import Control.Monad.Trans.Except (ExceptT)

-- selective
import Control.Selective (Selective (select))

-- simple-affine-space
import Data.VectorSpace

-- mmorph
import Control.Monad.Morph

-- automaton

import Data.Align (Align, Semialign)
import Data.Semialign (Align (..), Semialign (..))
import Data.Stream hiding (hoist')
import Data.Stream qualified as StreamT
import Data.Stream.Final (Final (..))
import Data.Stream.Final qualified as Final (fromFinal, toFinal)
import Data.Stream.Result

{- | An optimized version of 'StreamT' which has an extra constructor for stateless streams.

In most cases, using 'OptimizedStreamT' is preferable over 'StreamT',
because building up bigger programs with 'StreamT' will build up big accumulations of trivial states.
The API of 'OptimizedStreamT' only keeps the nontrivial parts of the state.

Semantically, both types are the same.
-}
data OptimizedStreamT m a
  = -- | Embed a 'StreamT'. Take care only to use this constructor on streams with nontrivial state.
    Stateful (StreamT m a)
  | -- | A stateless stream is simply an action in a monad which is performed repetitively.
    Stateless (m a)
  deriving ((forall a b.
 (a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b)
-> (forall a b. a -> OptimizedStreamT m b -> OptimizedStreamT m a)
-> Functor (OptimizedStreamT m)
forall a b. a -> OptimizedStreamT m b -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (m :: Type -> Type) a b.
Functor m =>
a -> OptimizedStreamT m b -> OptimizedStreamT m a
forall (m :: Type -> Type) a b.
Functor m =>
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall (m :: Type -> Type) a b.
Functor m =>
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
fmap :: forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
$c<$ :: forall (m :: Type -> Type) a b.
Functor m =>
a -> OptimizedStreamT m b -> OptimizedStreamT m a
<$ :: forall a b. a -> OptimizedStreamT m b -> OptimizedStreamT m a
Functor)

{- | Remove the optimization layer.

For stateful streams, this is just the identity.
A stateless stream is encoded as a stream with state '()'.
-}
toStreamT :: (Functor m) => OptimizedStreamT m b -> StreamT m b
toStreamT :: forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT (Stateful StreamT m b
stream) = StreamT m b
stream
toStreamT (Stateless m b
m) = StreamT {state :: ()
state = (), step :: () -> m (Result () b)
step = m (Result () b) -> () -> m (Result () b)
forall a b. a -> b -> a
const (m (Result () b) -> () -> m (Result () b))
-> m (Result () b) -> () -> m (Result () b)
forall a b. (a -> b) -> a -> b
$ () -> b -> Result () b
forall s a. s -> a -> Result s a
Result () (b -> Result () b) -> m b -> m (Result () b)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> m b
m}
{-# INLINE toStreamT #-}

-- | Only builds up tuples of states if both streams are stateful.
instance (Applicative m) => Applicative (OptimizedStreamT m) where
  pure :: forall a. a -> OptimizedStreamT m a
pure = m a -> OptimizedStreamT m a
forall (m :: Type -> Type) a. m a -> OptimizedStreamT m a
Stateless (m a -> OptimizedStreamT m a)
-> (a -> m a) -> a -> OptimizedStreamT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> m a
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure
  {-# INLINE pure #-}

  Stateful StreamT m (a -> b)
stream1 <*> :: forall a b.
OptimizedStreamT m (a -> b)
-> OptimizedStreamT m a -> OptimizedStreamT m b
<*> Stateful StreamT m a
stream2 = StreamT m b -> OptimizedStreamT m b
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT m b -> OptimizedStreamT m b)
-> StreamT m b -> OptimizedStreamT m b
forall a b. (a -> b) -> a -> b
$ StreamT m (a -> b)
stream1 StreamT m (a -> b) -> StreamT m a -> StreamT m b
forall a b. StreamT m (a -> b) -> StreamT m a -> StreamT m b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> StreamT m a
stream2
  Stateless m (a -> b)
m <*> Stateful (StreamT s
state0 s -> m (Result s a)
step) = StreamT m b -> OptimizedStreamT m b
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT m b -> OptimizedStreamT m b)
-> StreamT m b -> OptimizedStreamT m b
forall a b. (a -> b) -> a -> b
$ s -> (s -> m (Result s b)) -> StreamT m b
forall (m :: Type -> Type) a s.
s -> (s -> m (Result s a)) -> StreamT m a
StreamT s
state0 ((s -> m (Result s b)) -> StreamT m b)
-> (s -> m (Result s b)) -> StreamT m b
forall a b. (a -> b) -> a -> b
$ \s
state -> (a -> b) -> Result s a -> Result s b
forall a b. (a -> b) -> Result s a -> Result s b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> b) -> Result s a -> Result s b)
-> ((a -> b) -> a -> b) -> (a -> b) -> Result s a -> Result s b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> b) -> a -> b
forall a b. (a -> b) -> a -> b
($) ((a -> b) -> Result s a -> Result s b)
-> m (a -> b) -> m (Result s a -> Result s b)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> m (a -> b)
m m (Result s a -> Result s b) -> m (Result s a) -> m (Result s b)
forall a b. m (a -> b) -> m a -> m b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> s -> m (Result s a)
step s
state
  Stateful (StreamT s
state0 s -> m (Result s (a -> b))
step) <*> Stateless m a
m = StreamT m b -> OptimizedStreamT m b
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT m b -> OptimizedStreamT m b)
-> StreamT m b -> OptimizedStreamT m b
forall a b. (a -> b) -> a -> b
$ s -> (s -> m (Result s b)) -> StreamT m b
forall (m :: Type -> Type) a s.
s -> (s -> m (Result s a)) -> StreamT m a
StreamT s
state0 ((s -> m (Result s b)) -> StreamT m b)
-> (s -> m (Result s b)) -> StreamT m b
forall a b. (a -> b) -> a -> b
$ \s
state -> (a -> Result s (a -> b) -> Result s b)
-> Result s (a -> b) -> a -> Result s b
forall a b c. (a -> b -> c) -> b -> a -> c
flip (((a -> b) -> b) -> Result s (a -> b) -> Result s b
forall a b. (a -> b) -> Result s a -> Result s b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (((a -> b) -> b) -> Result s (a -> b) -> Result s b)
-> (a -> (a -> b) -> b) -> a -> Result s (a -> b) -> Result s b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a -> b) -> a -> b) -> a -> (a -> b) -> b
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> b) -> a -> b
forall a b. (a -> b) -> a -> b
($)) (Result s (a -> b) -> a -> Result s b)
-> m (Result s (a -> b)) -> m (a -> Result s b)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> s -> m (Result s (a -> b))
step s
state m (a -> Result s b) -> m a -> m (Result s b)
forall a b. m (a -> b) -> m a -> m b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> m a
m
  Stateless m (a -> b)
mf <*> Stateless m a
ma = m b -> OptimizedStreamT m b
forall (m :: Type -> Type) a. m a -> OptimizedStreamT m a
Stateless (m b -> OptimizedStreamT m b) -> m b -> OptimizedStreamT m b
forall a b. (a -> b) -> a -> b
$ m (a -> b)
mf m (a -> b) -> m a -> m b
forall a b. m (a -> b) -> m a -> m b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> m a
ma
  {-# INLINE (<*>) #-}

deriving via Ap (OptimizedStreamT m) a instance (Applicative m, Num a) => Num (OptimizedStreamT m a)

instance (Applicative m, Fractional a) => Fractional (OptimizedStreamT m a) where
  fromRational :: Rational -> OptimizedStreamT m a
fromRational = a -> OptimizedStreamT m a
forall a. a -> OptimizedStreamT m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (a -> OptimizedStreamT m a)
-> (Rational -> a) -> Rational -> OptimizedStreamT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> a
forall a. Fractional a => Rational -> a
fromRational
  recip :: OptimizedStreamT m a -> OptimizedStreamT m a
recip = (a -> a) -> OptimizedStreamT m a -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Fractional a => a -> a
recip

instance (Applicative m, Floating a) => Floating (OptimizedStreamT m a) where
  pi :: OptimizedStreamT m a
pi = a -> OptimizedStreamT m a
forall a. a -> OptimizedStreamT m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure a
forall a. Floating a => a
pi
  exp :: OptimizedStreamT m a -> OptimizedStreamT m a
exp = (a -> a) -> OptimizedStreamT m a -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Floating a => a -> a
exp
  log :: OptimizedStreamT m a -> OptimizedStreamT m a
log = (a -> a) -> OptimizedStreamT m a -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Floating a => a -> a
log
  sin :: OptimizedStreamT m a -> OptimizedStreamT m a
sin = (a -> a) -> OptimizedStreamT m a -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Floating a => a -> a
sin
  cos :: OptimizedStreamT m a -> OptimizedStreamT m a
cos = (a -> a) -> OptimizedStreamT m a -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Floating a => a -> a
cos
  asin :: OptimizedStreamT m a -> OptimizedStreamT m a
asin = (a -> a) -> OptimizedStreamT m a -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Floating a => a -> a
asin
  acos :: OptimizedStreamT m a -> OptimizedStreamT m a
acos = (a -> a) -> OptimizedStreamT m a -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Floating a => a -> a
acos
  atan :: OptimizedStreamT m a -> OptimizedStreamT m a
atan = (a -> a) -> OptimizedStreamT m a -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Floating a => a -> a
atan
  sinh :: OptimizedStreamT m a -> OptimizedStreamT m a
sinh = (a -> a) -> OptimizedStreamT m a -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Floating a => a -> a
sinh
  cosh :: OptimizedStreamT m a -> OptimizedStreamT m a
cosh = (a -> a) -> OptimizedStreamT m a -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Floating a => a -> a
cosh
  asinh :: OptimizedStreamT m a -> OptimizedStreamT m a
asinh = (a -> a) -> OptimizedStreamT m a -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Floating a => a -> a
asinh
  acosh :: OptimizedStreamT m a -> OptimizedStreamT m a
acosh = (a -> a) -> OptimizedStreamT m a -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Floating a => a -> a
acosh
  atanh :: OptimizedStreamT m a -> OptimizedStreamT m a
atanh = (a -> a) -> OptimizedStreamT m a -> OptimizedStreamT m a
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> a
forall a. Floating a => a -> a
atanh

instance (VectorSpace v s, Eq s, Floating s, Applicative m) => VectorSpace (OptimizedStreamT m v) (OptimizedStreamT m s) where
  zeroVector :: OptimizedStreamT m v
zeroVector = v -> OptimizedStreamT m v
forall a. a -> OptimizedStreamT m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure v
forall v a. VectorSpace v a => v
zeroVector
  *^ :: OptimizedStreamT m s
-> OptimizedStreamT m v -> OptimizedStreamT m v
(*^) = (s -> v -> v)
-> OptimizedStreamT m s
-> OptimizedStreamT m v
-> OptimizedStreamT m v
forall a b c.
(a -> b -> c)
-> OptimizedStreamT m a
-> OptimizedStreamT m b
-> OptimizedStreamT m c
forall (f :: Type -> Type) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 s -> v -> v
forall v a. VectorSpace v a => a -> v -> v
(*^)
  ^+^ :: OptimizedStreamT m v
-> OptimizedStreamT m v -> OptimizedStreamT m v
(^+^) = (v -> v -> v)
-> OptimizedStreamT m v
-> OptimizedStreamT m v
-> OptimizedStreamT m v
forall a b c.
(a -> b -> c)
-> OptimizedStreamT m a
-> OptimizedStreamT m b
-> OptimizedStreamT m c
forall (f :: Type -> Type) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 v -> v -> v
forall v a. VectorSpace v a => v -> v -> v
(^+^)
  dot :: OptimizedStreamT m v
-> OptimizedStreamT m v -> OptimizedStreamT m s
dot = (v -> v -> s)
-> OptimizedStreamT m v
-> OptimizedStreamT m v
-> OptimizedStreamT m s
forall a b c.
(a -> b -> c)
-> OptimizedStreamT m a
-> OptimizedStreamT m b
-> OptimizedStreamT m c
forall (f :: Type -> Type) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 v -> v -> s
forall v a. VectorSpace v a => v -> v -> a
dot
  normalize :: OptimizedStreamT m v -> OptimizedStreamT m v
normalize = (v -> v) -> OptimizedStreamT m v -> OptimizedStreamT m v
forall a b.
(a -> b) -> OptimizedStreamT m a -> OptimizedStreamT m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap v -> v
forall v a. VectorSpace v a => v -> v
normalize

instance (Alternative m) => Alternative (OptimizedStreamT m) where
  empty :: forall a. OptimizedStreamT m a
empty = m a -> OptimizedStreamT m a
forall (m :: Type -> Type) a. m a -> OptimizedStreamT m a
Stateless m a
forall a. m a
forall (f :: Type -> Type) a. Alternative f => f a
empty
  {-# INLINE empty #-}

  -- The semantics prescribe that we save the state which stream was selected.
  OptimizedStreamT m a
stream1 <|> :: forall a.
OptimizedStreamT m a
-> OptimizedStreamT m a -> OptimizedStreamT m a
<|> OptimizedStreamT m a
stream2 = StreamT m a -> OptimizedStreamT m a
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT m a -> OptimizedStreamT m a)
-> StreamT m a -> OptimizedStreamT m a
forall a b. (a -> b) -> a -> b
$ OptimizedStreamT m a -> StreamT m a
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT m a
stream1 StreamT m a -> StreamT m a -> StreamT m a
forall a. StreamT m a -> StreamT m a -> StreamT m a
forall (f :: Type -> Type) a. Alternative f => f a -> f a -> f a
<|> OptimizedStreamT m a -> StreamT m a
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT m a
stream2
  {-# INLINE (<|>) #-}

  many :: forall a. OptimizedStreamT m a -> OptimizedStreamT m [a]
many OptimizedStreamT m a
stream = StreamT m [a] -> OptimizedStreamT m [a]
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT m [a] -> OptimizedStreamT m [a])
-> StreamT m [a] -> OptimizedStreamT m [a]
forall a b. (a -> b) -> a -> b
$ StreamT m a -> StreamT m [a]
forall a. StreamT m a -> StreamT m [a]
forall (f :: Type -> Type) a. Alternative f => f a -> f [a]
many (StreamT m a -> StreamT m [a]) -> StreamT m a -> StreamT m [a]
forall a b. (a -> b) -> a -> b
$ OptimizedStreamT m a -> StreamT m a
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT m a
stream
  {-# INLINE many #-}

  some :: forall a. OptimizedStreamT m a -> OptimizedStreamT m [a]
some OptimizedStreamT m a
stream = StreamT m [a] -> OptimizedStreamT m [a]
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT m [a] -> OptimizedStreamT m [a])
-> StreamT m [a] -> OptimizedStreamT m [a]
forall a b. (a -> b) -> a -> b
$ StreamT m a -> StreamT m [a]
forall a. StreamT m a -> StreamT m [a]
forall (f :: Type -> Type) a. Alternative f => f a -> f [a]
some (StreamT m a -> StreamT m [a]) -> StreamT m a -> StreamT m [a]
forall a b. (a -> b) -> a -> b
$ OptimizedStreamT m a -> StreamT m a
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT m a
stream
  {-# INLINE some #-}

instance (Selective m) => Selective (OptimizedStreamT m) where
  select :: forall a b.
OptimizedStreamT m (Either a b)
-> OptimizedStreamT m (a -> b) -> OptimizedStreamT m b
select (Stateless m (Either a b)
mab) (Stateless m (a -> b)
f) = m b -> OptimizedStreamT m b
forall (m :: Type -> Type) a. m a -> OptimizedStreamT m a
Stateless (m b -> OptimizedStreamT m b) -> m b -> OptimizedStreamT m b
forall a b. (a -> b) -> a -> b
$ m (Either a b) -> m (a -> b) -> m b
forall a b. m (Either a b) -> m (a -> b) -> m b
forall (f :: Type -> Type) a b.
Selective f =>
f (Either a b) -> f (a -> b) -> f b
select m (Either a b)
mab m (a -> b)
f
  select OptimizedStreamT m (Either a b)
stream1 OptimizedStreamT m (a -> b)
stream2 = StreamT m b -> OptimizedStreamT m b
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT m b -> OptimizedStreamT m b)
-> StreamT m b -> OptimizedStreamT m b
forall a b. (a -> b) -> a -> b
$ StreamT m (Either a b) -> StreamT m (a -> b) -> StreamT m b
forall a b.
StreamT m (Either a b) -> StreamT m (a -> b) -> StreamT m b
forall (f :: Type -> Type) a b.
Selective f =>
f (Either a b) -> f (a -> b) -> f b
select (OptimizedStreamT m (Either a b) -> StreamT m (Either a b)
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT m (Either a b)
stream1) (OptimizedStreamT m (a -> b) -> StreamT m (a -> b)
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT m (a -> b)
stream2)

instance (Semialign m) => Semialign (OptimizedStreamT m) where
  align :: forall a b.
OptimizedStreamT m a
-> OptimizedStreamT m b -> OptimizedStreamT m (These a b)
align (Stateless m a
ma) (Stateless m b
mb) = m (These a b) -> OptimizedStreamT m (These a b)
forall (m :: Type -> Type) a. m a -> OptimizedStreamT m a
Stateless (m (These a b) -> OptimizedStreamT m (These a b))
-> m (These a b) -> OptimizedStreamT m (These a b)
forall a b. (a -> b) -> a -> b
$ m a -> m b -> m (These a b)
forall a b. m a -> m b -> m (These a b)
forall (f :: Type -> Type) a b.
Semialign f =>
f a -> f b -> f (These a b)
align m a
ma m b
mb
  align OptimizedStreamT m a
stream1 OptimizedStreamT m b
stream2 = StreamT m (These a b) -> OptimizedStreamT m (These a b)
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT m (These a b) -> OptimizedStreamT m (These a b))
-> StreamT m (These a b) -> OptimizedStreamT m (These a b)
forall a b. (a -> b) -> a -> b
$ StreamT m a -> StreamT m b -> StreamT m (These a b)
forall a b. StreamT m a -> StreamT m b -> StreamT m (These a b)
forall (f :: Type -> Type) a b.
Semialign f =>
f a -> f b -> f (These a b)
align (OptimizedStreamT m a -> StreamT m a
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT m a
stream1) (OptimizedStreamT m b -> StreamT m b
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT m b
stream2)

instance (Align m) => Align (OptimizedStreamT m) where
  nil :: forall a. OptimizedStreamT m a
nil = m a -> OptimizedStreamT m a
forall (m :: Type -> Type) a. m a -> OptimizedStreamT m a
Stateless m a
forall a. m a
forall (f :: Type -> Type) a. Align f => f a
nil

instance MFunctor OptimizedStreamT where
  hoist :: forall (m :: Type -> Type) (n :: Type -> Type) b.
Monad m =>
(forall a. m a -> n a)
-> OptimizedStreamT m b -> OptimizedStreamT n b
hoist = (forall x. m x -> n x)
-> OptimizedStreamT m b -> OptimizedStreamT n b
forall (m1 :: Type -> Type) (m2 :: Type -> Type) a.
(forall x. m1 x -> m2 x)
-> OptimizedStreamT m1 a -> OptimizedStreamT m2 a
hoist'
  {-# INLINE hoist #-}

-- | Like 'hoist', but without the @'Monad' m2@ constraint.
hoist' :: (forall x. m1 x -> m2 x) -> OptimizedStreamT m1 a -> OptimizedStreamT m2 a
hoist' :: forall (m1 :: Type -> Type) (m2 :: Type -> Type) a.
(forall x. m1 x -> m2 x)
-> OptimizedStreamT m1 a -> OptimizedStreamT m2 a
hoist' forall x. m1 x -> m2 x
f (Stateful StreamT m1 a
stream) = StreamT m2 a -> OptimizedStreamT m2 a
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT m2 a -> OptimizedStreamT m2 a)
-> StreamT m2 a -> OptimizedStreamT m2 a
forall a b. (a -> b) -> a -> b
$ (forall x. m1 x -> m2 x) -> StreamT m1 a -> StreamT m2 a
forall (m1 :: Type -> Type) (m2 :: Type -> Type) a.
(forall x. m1 x -> m2 x) -> StreamT m1 a -> StreamT m2 a
StreamT.hoist' m1 x -> m2 x
forall x. m1 x -> m2 x
f StreamT m1 a
stream
hoist' forall x. m1 x -> m2 x
f (Stateless m1 a
m) = m2 a -> OptimizedStreamT m2 a
forall (m :: Type -> Type) a. m a -> OptimizedStreamT m a
Stateless (m2 a -> OptimizedStreamT m2 a) -> m2 a -> OptimizedStreamT m2 a
forall a b. (a -> b) -> a -> b
$ m1 a -> m2 a
forall x. m1 x -> m2 x
f m1 a
m
{-# INLINE hoist' #-}

-- | Change the output type and effect of a stream without changing its state type.
mapOptimizedStreamT :: (Functor m, Functor n) => (forall s. m (Result s a) -> n (Result s b)) -> OptimizedStreamT m a -> OptimizedStreamT n b
mapOptimizedStreamT :: forall (m :: Type -> Type) (n :: Type -> Type) a b.
(Functor m, Functor n) =>
(forall s. m (Result s a) -> n (Result s b))
-> OptimizedStreamT m a -> OptimizedStreamT n b
mapOptimizedStreamT forall s. m (Result s a) -> n (Result s b)
f (Stateful StreamT m a
stream) = StreamT n b -> OptimizedStreamT n b
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT n b -> OptimizedStreamT n b)
-> StreamT n b -> OptimizedStreamT n b
forall a b. (a -> b) -> a -> b
$ (forall s. m (Result s a) -> n (Result s b))
-> StreamT m a -> StreamT n b
forall (m :: Type -> Type) (n :: Type -> Type) a b.
(Functor m, Functor n) =>
(forall s. m (Result s a) -> n (Result s b))
-> StreamT m a -> StreamT n b
withStreamT m (Result s a) -> n (Result s b)
forall s. m (Result s a) -> n (Result s b)
f StreamT m a
stream
mapOptimizedStreamT forall s. m (Result s a) -> n (Result s b)
f (Stateless m a
m) = n b -> OptimizedStreamT n b
forall (m :: Type -> Type) a. m a -> OptimizedStreamT m a
Stateless (n b -> OptimizedStreamT n b) -> n b -> OptimizedStreamT n b
forall a b. (a -> b) -> a -> b
$ (Result () b -> b) -> n (Result () b) -> n b
forall a b. (a -> b) -> n a -> n b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap Result () b -> b
forall s a. Result s a -> a
output (n (Result () b) -> n b) -> n (Result () b) -> n b
forall a b. (a -> b) -> a -> b
$ m (Result () a) -> n (Result () b)
forall s. m (Result s a) -> n (Result s b)
f (m (Result () a) -> n (Result () b))
-> m (Result () a) -> n (Result () b)
forall a b. (a -> b) -> a -> b
$ (a -> Result () a) -> m a -> m (Result () a)
forall a b. (a -> b) -> m a -> m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (() -> a -> Result () a
forall s a. s -> a -> Result s a
Result ()) m a
m
{-# INLINE mapOptimizedStreamT #-}

{- | Map a monad-independent morphism of streams to optimized streams.

In contrast to 'handleOptimized', the stream morphism must be independent of the monad.
-}
withOptimized :: (Monad n) => (forall m. (Monad m) => StreamT m a -> StreamT m b) -> OptimizedStreamT n a -> OptimizedStreamT n b
withOptimized :: forall (n :: Type -> Type) a b.
Monad n =>
(forall (m :: Type -> Type). Monad m => StreamT m a -> StreamT m b)
-> OptimizedStreamT n a -> OptimizedStreamT n b
withOptimized forall (m :: Type -> Type). Monad m => StreamT m a -> StreamT m b
f OptimizedStreamT n a
stream = StreamT n b -> OptimizedStreamT n b
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT n b -> OptimizedStreamT n b)
-> StreamT n b -> OptimizedStreamT n b
forall a b. (a -> b) -> a -> b
$ StreamT n a -> StreamT n b
forall (m :: Type -> Type). Monad m => StreamT m a -> StreamT m b
f (StreamT n a -> StreamT n b) -> StreamT n a -> StreamT n b
forall a b. (a -> b) -> a -> b
$ OptimizedStreamT n a -> StreamT n a
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT n a
stream

{- | Map a morphism of streams to optimized streams.

In contrast to 'withOptimized', the monad type is allowed to change.
-}
handleOptimized :: (Functor m) => (StreamT m a -> StreamT n b) -> OptimizedStreamT m a -> OptimizedStreamT n b
handleOptimized :: forall (m :: Type -> Type) a (n :: Type -> Type) b.
Functor m =>
(StreamT m a -> StreamT n b)
-> OptimizedStreamT m a -> OptimizedStreamT n b
handleOptimized StreamT m a -> StreamT n b
f OptimizedStreamT m a
stream = StreamT n b -> OptimizedStreamT n b
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT n b -> OptimizedStreamT n b)
-> StreamT n b -> OptimizedStreamT n b
forall a b. (a -> b) -> a -> b
$ StreamT m a -> StreamT n b
f (StreamT m a -> StreamT n b) -> StreamT m a -> StreamT n b
forall a b. (a -> b) -> a -> b
$ OptimizedStreamT m a -> StreamT m a
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT m a
stream

{- | Run a stream with trivial output.

See 'Data.Stream.reactimate'.
-}
reactimate :: (Monad m) => OptimizedStreamT m () -> m void
reactimate :: forall (m :: Type -> Type) void.
Monad m =>
OptimizedStreamT m () -> m void
reactimate (Stateful StreamT m ()
stream) = StreamT m () -> m void
forall (m :: Type -> Type) void. Monad m => StreamT m () -> m void
StreamT.reactimate StreamT m ()
stream
reactimate (Stateless m ()
f) = m void
go
  where
    go :: m void
go = m ()
f m () -> m void -> m void
forall a b. m a -> m b -> m b
forall (f :: Type -> Type) a b. Applicative f => f a -> f b -> f b
*> m void
go
{-# INLINE reactimate #-}

{- | A stateless stream.

This function is typically preferable over 'Data.Stream.constM',
since the optimized version doesn't create a state type.
-}
constM :: m a -> OptimizedStreamT m a
constM :: forall (m :: Type -> Type) a. m a -> OptimizedStreamT m a
constM = m a -> OptimizedStreamT m a
forall (m :: Type -> Type) a. m a -> OptimizedStreamT m a
Stateless
{-# INLINE constM #-}

-- | Perform one step of a stream, resulting in an updated stream and an output value.
stepOptimizedStream :: (Functor m) => OptimizedStreamT m a -> m (Result (OptimizedStreamT m a) a)
stepOptimizedStream :: forall (m :: Type -> Type) a.
Functor m =>
OptimizedStreamT m a -> m (Result (OptimizedStreamT m a) a)
stepOptimizedStream (Stateful StreamT m a
stream) = (StreamT m a -> OptimizedStreamT m a)
-> Result (StreamT m a) a -> Result (OptimizedStreamT m a) a
forall s1 s2 a. (s1 -> s2) -> Result s1 a -> Result s2 a
mapResultState StreamT m a -> OptimizedStreamT m a
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (Result (StreamT m a) a -> Result (OptimizedStreamT m a) a)
-> m (Result (StreamT m a) a)
-> m (Result (OptimizedStreamT m a) a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> StreamT m a -> m (Result (StreamT m a) a)
forall (m :: Type -> Type) a.
Functor m =>
StreamT m a -> m (Result (StreamT m a) a)
stepStream StreamT m a
stream
stepOptimizedStream oa :: OptimizedStreamT m a
oa@(Stateless m a
m) = OptimizedStreamT m a -> a -> Result (OptimizedStreamT m a) a
forall s a. s -> a -> Result s a
Result OptimizedStreamT m a
oa (a -> Result (OptimizedStreamT m a) a)
-> m a -> m (Result (OptimizedStreamT m a) a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> m a
m
{-# INLINE stepOptimizedStream #-}

{- | Translate to the final encoding of streams.

This will typically be a performance penalty.
-}
toFinal :: (Functor m) => OptimizedStreamT m a -> Final m a
toFinal :: forall (m :: Type -> Type) a.
Functor m =>
OptimizedStreamT m a -> Final m a
toFinal (Stateful StreamT m a
stream) = StreamT m a -> Final m a
forall (m :: Type -> Type) a. Functor m => StreamT m a -> Final m a
Final.toFinal StreamT m a
stream
toFinal (Stateless m a
f) = Final m a
go
  where
    go :: Final m a
go = m (Result (Final m a) a) -> Final m a
forall (m :: Type -> Type) a. m (Result (Final m a) a) -> Final m a
Final (m (Result (Final m a) a) -> Final m a)
-> m (Result (Final m a) a) -> Final m a
forall a b. (a -> b) -> a -> b
$ Final m a -> a -> Result (Final m a) a
forall s a. s -> a -> Result s a
Result Final m a
go (a -> Result (Final m a) a) -> m a -> m (Result (Final m a) a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> m a
f
{-# INLINE toFinal #-}

{- | Translate a stream from final encoding to stateful, initial encoding.
  The internal state is the stream itself.
-}
fromFinal :: Final m a -> OptimizedStreamT m a
fromFinal :: forall (m :: Type -> Type) a. Final m a -> OptimizedStreamT m a
fromFinal = StreamT m a -> OptimizedStreamT m a
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT m a -> OptimizedStreamT m a)
-> (Final m a -> StreamT m a) -> Final m a -> OptimizedStreamT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Final m a -> StreamT m a
forall (m :: Type -> Type) a. Final m a -> StreamT m a
Final.fromFinal
{-# INLINE fromFinal #-}

-- | See 'Data.Stream.concatS'.
concatS :: (Monad m) => OptimizedStreamT m [a] -> OptimizedStreamT m a
concatS :: forall (m :: Type -> Type) a.
Monad m =>
OptimizedStreamT m [a] -> OptimizedStreamT m a
concatS OptimizedStreamT m [a]
stream = StreamT m a -> OptimizedStreamT m a
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT m a -> OptimizedStreamT m a)
-> StreamT m a -> OptimizedStreamT m a
forall a b. (a -> b) -> a -> b
$ StreamT m [a] -> StreamT m a
forall (m :: Type -> Type) a.
Monad m =>
StreamT m [a] -> StreamT m a
StreamT.concatS (StreamT m [a] -> StreamT m a) -> StreamT m [a] -> StreamT m a
forall a b. (a -> b) -> a -> b
$ OptimizedStreamT m [a] -> StreamT m [a]
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT m [a]
stream
{-# INLINE concatS #-}

-- | See 'Data.Stream.exceptS'.
exceptS :: (Monad m) => OptimizedStreamT (ExceptT e m) b -> OptimizedStreamT m (Either e b)
exceptS :: forall (m :: Type -> Type) e b.
Monad m =>
OptimizedStreamT (ExceptT e m) b -> OptimizedStreamT m (Either e b)
exceptS OptimizedStreamT (ExceptT e m) b
stream = StreamT m (Either e b) -> OptimizedStreamT m (Either e b)
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT m (Either e b) -> OptimizedStreamT m (Either e b))
-> StreamT m (Either e b) -> OptimizedStreamT m (Either e b)
forall a b. (a -> b) -> a -> b
$ StreamT (ExceptT e m) b -> StreamT m (Either e b)
forall (m :: Type -> Type) e b.
Applicative m =>
StreamT (ExceptT e m) b -> StreamT m (Either e b)
StreamT.exceptS (StreamT (ExceptT e m) b -> StreamT m (Either e b))
-> StreamT (ExceptT e m) b -> StreamT m (Either e b)
forall a b. (a -> b) -> a -> b
$ OptimizedStreamT (ExceptT e m) b -> StreamT (ExceptT e m) b
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT (ExceptT e m) b
stream
{-# INLINE exceptS #-}

-- | See 'Data.Stream.applyExcept'.
applyExcept :: (Monad m) => OptimizedStreamT (ExceptT (e1 -> e2) m) a -> OptimizedStreamT (ExceptT e1 m) a -> OptimizedStreamT (ExceptT e2 m) a
applyExcept :: forall (m :: Type -> Type) e1 e2 a.
Monad m =>
OptimizedStreamT (ExceptT (e1 -> e2) m) a
-> OptimizedStreamT (ExceptT e1 m) a
-> OptimizedStreamT (ExceptT e2 m) a
applyExcept OptimizedStreamT (ExceptT (e1 -> e2) m) a
streamF OptimizedStreamT (ExceptT e1 m) a
streamA = StreamT (ExceptT e2 m) a -> OptimizedStreamT (ExceptT e2 m) a
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT (ExceptT e2 m) a -> OptimizedStreamT (ExceptT e2 m) a)
-> StreamT (ExceptT e2 m) a -> OptimizedStreamT (ExceptT e2 m) a
forall a b. (a -> b) -> a -> b
$ StreamT (ExceptT (e1 -> e2) m) a
-> StreamT (ExceptT e1 m) a -> StreamT (ExceptT e2 m) a
forall (m :: Type -> Type) e1 e2 a.
Monad m =>
StreamT (ExceptT (e1 -> e2) m) a
-> StreamT (ExceptT e1 m) a -> StreamT (ExceptT e2 m) a
StreamT.applyExcept (OptimizedStreamT (ExceptT (e1 -> e2) m) a
-> StreamT (ExceptT (e1 -> e2) m) a
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT (ExceptT (e1 -> e2) m) a
streamF) (OptimizedStreamT (ExceptT e1 m) a -> StreamT (ExceptT e1 m) a
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT (ExceptT e1 m) a
streamA)
{-# INLINE applyExcept #-}

-- | See 'Data.Stream.selectExcept'.
selectExcept :: (Monad m) => OptimizedStreamT (ExceptT (Either e1 e2) m) a -> OptimizedStreamT (ExceptT (e1 -> e2) m) a -> OptimizedStreamT (ExceptT e2 m) a
selectExcept :: forall (m :: Type -> Type) e1 e2 a.
Monad m =>
OptimizedStreamT (ExceptT (Either e1 e2) m) a
-> OptimizedStreamT (ExceptT (e1 -> e2) m) a
-> OptimizedStreamT (ExceptT e2 m) a
selectExcept OptimizedStreamT (ExceptT (Either e1 e2) m) a
streamE OptimizedStreamT (ExceptT (e1 -> e2) m) a
streamF = StreamT (ExceptT e2 m) a -> OptimizedStreamT (ExceptT e2 m) a
forall (m :: Type -> Type) a. StreamT m a -> OptimizedStreamT m a
Stateful (StreamT (ExceptT e2 m) a -> OptimizedStreamT (ExceptT e2 m) a)
-> StreamT (ExceptT e2 m) a -> OptimizedStreamT (ExceptT e2 m) a
forall a b. (a -> b) -> a -> b
$ StreamT (ExceptT (Either e1 e2) m) a
-> StreamT (ExceptT (e1 -> e2) m) a -> StreamT (ExceptT e2 m) a
forall (m :: Type -> Type) e1 e2 a.
Monad m =>
StreamT (ExceptT (Either e1 e2) m) a
-> StreamT (ExceptT (e1 -> e2) m) a -> StreamT (ExceptT e2 m) a
StreamT.selectExcept (OptimizedStreamT (ExceptT (Either e1 e2) m) a
-> StreamT (ExceptT (Either e1 e2) m) a
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT (ExceptT (Either e1 e2) m) a
streamE) (OptimizedStreamT (ExceptT (e1 -> e2) m) a
-> StreamT (ExceptT (e1 -> e2) m) a
forall (m :: Type -> Type) b.
Functor m =>
OptimizedStreamT m b -> StreamT m b
toStreamT OptimizedStreamT (ExceptT (e1 -> e2) m) a
streamF)
{-# INLINE selectExcept #-}