module Next.Stream.Type
  (
    {- * Type -} Stream (..),
  )
  where

import Essentials
import Next.Producer.Type

import Control.Monad (ap)
import SupplyChain ((>->))

import qualified Next.Pipe as Pipe
import qualified Next.Producer as Producer

newtype Stream action item =
    Stream{ forall (action :: * -> *) item.
Stream action item -> Producer action item
producer :: Producer action item }

instance Semigroup (Stream action item) where
    Stream action item
a <> :: Stream action item -> Stream action item -> Stream action item
<> Stream action item
b = forall (action :: * -> *) item.
Producer action item -> Stream action item
Stream forall a b. (a -> b) -> a -> b
$ forall (up :: * -> *) item (action :: * -> *).
ProducerPlus up action item
-> ProducerPlus up action item -> ProducerPlus up action item
Producer.append (forall (action :: * -> *) item.
Stream action item -> Producer action item
producer Stream action item
a) (forall (action :: * -> *) item.
Stream action item -> Producer action item
producer Stream action item
b)

instance Monoid (Stream action item) where
    mempty :: Stream action item
mempty = forall (action :: * -> *) item.
Producer action item -> Stream action item
Stream forall (up :: * -> *) item (action :: * -> *).
ProducerPlus up action item
Producer.empty

instance Functor (Stream action) where
    fmap :: forall a b. (a -> b) -> Stream action a -> Stream action b
fmap a -> b
f (Stream Producer action a
xs) = forall (action :: * -> *) item.
Producer action item -> Stream action item
Stream forall a b. (a -> b) -> a -> b
$ Producer action a
xs forall (up :: * -> *) (middle :: * -> *) (action :: * -> *)
       (down :: * -> *).
Vendor up middle action
-> Vendor middle down action -> Vendor up down action
>-> forall item1 item2 (action :: * -> *) (up :: * -> *).
(item1 -> Job up action item2) -> PipePlus up action item1 item2
Pipe.map (\a
x -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (a -> b
f a
x))

instance Applicative (Stream action) where
    pure :: forall a. a -> Stream action a
pure a
x = forall (action :: * -> *) item.
Producer action item -> Stream action item
Stream forall a b. (a -> b) -> a -> b
$ forall (up :: * -> *) item (action :: * -> *).
Job up action item -> ProducerPlus up action item
Producer.singleton (forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x)
    <*> :: forall a b.
Stream action (a -> b) -> Stream action a -> Stream action b
(<*>) = forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap

instance Monad (Stream action) where
    (Stream Producer action a
xs) >>= :: forall a b.
Stream action a -> (a -> Stream action b) -> Stream action b
>>= a -> Stream action b
f = forall (action :: * -> *) item.
Producer action item -> Stream action item
Stream forall a b. (a -> b) -> a -> b
$
        Producer action a
xs forall (up :: * -> *) (middle :: * -> *) (action :: * -> *)
       (down :: * -> *).
Vendor up middle action
-> Vendor middle down action -> Vendor up down action
>-> forall item1 item2 (action :: * -> *).
(item1 -> Producer action item2) -> Pipe action item1 item2
Pipe.concatMapProducer (\a
x -> forall (action :: * -> *) item.
Stream action item -> Producer action item
producer (a -> Stream action b
f a
x))