packages feed

pipes 2.5.0 → 3.0.0

raw patch · 30 files changed

+4656/−3743 lines, 30 filesdep −index-corePVP ok

version bump matches the API change (PVP)

Dependencies removed: index-core

API changes (from Hackage documentation)

- Control.Frame: (<-<) :: Monad m => Frame c m (M b) C r -> Frame b m (M a) C r -> Frame c m (M a) C r
- Control.Frame: (>->) :: Monad m => Frame b m (M a) C r -> Frame c m (M b) C r -> Frame c m (M a) C r
- Control.Frame: FrameC :: Frame b m (M a) C r -> FrameC m r a b
- Control.Frame: [Await] :: (a -> x (O a)) -> FrameF b x (O a)
- Control.Frame: [Close] :: x C -> FrameF b x (O a)
- Control.Frame: [Yield] :: b -> x i -> FrameF b x i
- Control.Frame: [unFrameC] :: FrameC m r a b -> Frame b m (M a) C r
- Control.Frame: await :: (Monad m) => Frame b m (M a) (M a) a
- Control.Frame: awaitF :: (Monad m) => Frame b m (M a) (M a) (Maybe a)
- Control.Frame: catchD :: (Monad m) => m () -> Frame b m i j r -> Frame b m i j r
- Control.Frame: catchF :: (Monad m) => m () -> Frame b m (M a) j r -> Frame b m (M a) j r
- Control.Frame: close :: (Monad m) => Frame b m (M a) C ()
- Control.Frame: data C
- Control.Frame: data FrameF b x i
- Control.Frame: data O a
- Control.Frame: finallyD :: (Monad m) => m () -> Frame b m i j r -> Frame b m i j r
- Control.Frame: finallyF :: (Monad m) => m () -> Frame b m (M a) j r -> Frame b m (M a) j r
- Control.Frame: idF :: (Monad m) => Frame a m (M a) C r
- Control.Frame: infixr 9 >->
- Control.Frame: instance Control.IMonad.Core.IFunctor (Control.Frame.FrameF b)
- Control.Frame: instance GHC.Base.Monad m => Control.Category.Category (Control.Frame.FrameC m r)
- Control.Frame: newtype FrameC m r a b
- Control.Frame: runFrame :: (Monad m) => Stack m r -> m r
- Control.Frame: type Frame b m i j r = IFreeT (FrameF (m (), b)) (U m) (r := j) i
- Control.Frame: type M a = O (Maybe a)
- Control.Frame: type Stack m r = Frame C m (M ()) C r
- Control.Frame: yield :: (Monad m) => b -> Frame b m i i ()
- Control.Frame: yieldF :: (Monad m) => m () -> b -> Frame b m i i ()
- Control.IMonad.Trans.Free: IFreeT :: m (IFreeF f r (IFreeT f m r)) i -> IFreeT f m r i
- Control.IMonad.Trans.Free: Return :: (r i) -> IFreeF f r i
- Control.IMonad.Trans.Free: Wrap :: (f x i) -> IFreeF f r i
- Control.IMonad.Trans.Free: [runIFreeT] :: IFreeT f m r i -> m (IFreeF f r (IFreeT f m r)) i
- Control.IMonad.Trans.Free: data IFreeF f r (x :: * -> *) i
- Control.IMonad.Trans.Free: instance (Control.IMonad.Core.IFunctor f, Control.IMonad.Core.IMonad m) => Control.IMonad.Core.IFunctor (Control.IMonad.Trans.Free.IFreeT f m)
- Control.IMonad.Trans.Free: instance (Control.IMonad.Core.IFunctor f, Control.IMonad.Core.IMonad m) => Control.IMonad.Core.IMonad (Control.IMonad.Trans.Free.IFreeT f m)
- Control.IMonad.Trans.Free: instance Control.IMonad.Core.IFunctor f => Control.IMonad.Trans.IMonadTrans (Control.IMonad.Trans.Free.IFreeT f)
- Control.IMonad.Trans.Free: liftF :: (IFunctor f, IMonad m) => f r :-> IFreeT f m r
- Control.IMonad.Trans.Free: newtype IFreeT f m r i
- Control.IMonad.Trans.Free: wrap :: (IMonad m) => f (IFreeT f m r) :-> IFreeT f m r
- Control.MFunctor: mapT :: (MFunctor t, Monad m, Monad n) => (forall a. m a -> n a) -> t m b -> t n b
- Control.Pipe.Core: (<+<) :: (Monad m) => Pipe b c m r -> Pipe a b m r -> Pipe a c m r
- Control.Pipe.Core: (>+>) :: (Monad m) => Pipe a b m r -> Pipe b c m r -> Pipe a c m r
- Control.Pipe.Core: Await :: (a -> Pipe a b m r) -> Pipe a b m r
- Control.Pipe.Core: M :: (m (Pipe a b m r)) -> Pipe a b m r
- Control.Pipe.Core: PipeC :: Pipe a b m r -> PipeC m r a b
- Control.Pipe.Core: Pure :: r -> Pipe a b m r
- Control.Pipe.Core: Yield :: b -> (Pipe a b m r) -> Pipe a b m r
- Control.Pipe.Core: [unPipeC] :: PipeC m r a b -> Pipe a b m r
- Control.Pipe.Core: await :: Pipe a b m a
- Control.Pipe.Core: data C
- Control.Pipe.Core: data Pipe a b m r
- Control.Pipe.Core: idP :: (Monad m) => Pipe a a m r
- Control.Pipe.Core: infixl 9 >+>
- Control.Pipe.Core: infixr 9 <+<
- Control.Pipe.Core: instance Control.Monad.Trans.Class.MonadTrans (Control.Pipe.Core.Pipe a b)
- Control.Pipe.Core: instance GHC.Base.Monad m => Control.Category.Category (Control.Pipe.Core.PipeC m r)
- Control.Pipe.Core: instance GHC.Base.Monad m => GHC.Base.Applicative (Control.Pipe.Core.Pipe a b m)
- Control.Pipe.Core: instance GHC.Base.Monad m => GHC.Base.Functor (Control.Pipe.Core.Pipe a b m)
- Control.Pipe.Core: instance GHC.Base.Monad m => GHC.Base.Monad (Control.Pipe.Core.Pipe a b m)
- Control.Pipe.Core: newtype PipeC m r a b
- Control.Pipe.Core: pipe :: (Monad m) => (a -> b) -> Pipe a b m r
- Control.Pipe.Core: runPipe :: (Monad m) => Pipeline m r -> m r
- Control.Pipe.Core: type Consumer b = Pipe b C
- Control.Pipe.Core: type Pipeline = Pipe () C
- Control.Pipe.Core: type Producer b = Pipe () b
- Control.Pipe.Core: yield :: b -> Pipe a b m ()
- Control.Proxy.Class: class Channel p where p1 >-> p2 = p2 <-< p1 p1 <-< p2 = p2 >-> p1
- Control.Proxy.Core: M :: (m (Proxy a' a b' b m r)) -> Proxy a' a b' b m r
- Control.Proxy.Core: Pure :: r -> Proxy a' a b' b m r
- Control.Proxy.Core: Request :: a' -> (a -> Proxy a' a b' b m r) -> Proxy a' a b' b m r
- Control.Proxy.Core: Respond :: b -> (b' -> Proxy a' a b' b m r) -> Proxy a' a b' b m r
- Control.Proxy.Core: data C
- Control.Proxy.Core: data Proxy a' a b' b m r
- Control.Proxy.Core: discard :: (Monad m) => () -> Proxy () a () C m r
- Control.Proxy.Core: ignore :: (Monad m) => a -> Proxy C () a () m r
- Control.Proxy.Core: instance Control.MFunctor.MFunctor (Control.Proxy.Core.Proxy a' a b' b)
- Control.Proxy.Core: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Proxy.Core.Proxy a' a b' b m)
- Control.Proxy.Core: instance Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Core.Proxy a' a b' b)
- Control.Proxy.Core: instance Control.Proxy.Class.Channel Control.Proxy.Core.Proxy
- Control.Proxy.Core: instance Control.Proxy.Class.Interact Control.Proxy.Core.Proxy
- Control.Proxy.Core: instance GHC.Base.Monad m => GHC.Base.Applicative (Control.Proxy.Core.Proxy a' a b' b m)
- Control.Proxy.Core: instance GHC.Base.Monad m => GHC.Base.Functor (Control.Proxy.Core.Proxy a' a b' b m)
- Control.Proxy.Core: instance GHC.Base.Monad m => GHC.Base.Monad (Control.Proxy.Core.Proxy a' a b' b m)
- Control.Proxy.Core: runProxy :: (Monad m) => (() -> Proxy a' () () b m r) -> m r
- Control.Proxy.Core: runProxyK :: (Monad m) => (() -> Proxy a () () b m r) -> (() -> m r)
- Control.Proxy.Core: runSession :: (Monad m) => (() -> Session m r) -> m r
- Control.Proxy.Core: runSessionK :: (Monad m) => (() -> Session m r) -> (() -> m r)
- Control.Proxy.Core: type Client req resp = Proxy req resp () C
- Control.Proxy.Core: type Server req resp = Proxy C () req resp
- Control.Proxy.Core: type Session = Proxy C () () C
- Control.Proxy.Pipe: runPipe :: (Monad m) => Pipeline m r -> m r
- Control.Proxy.Pipe: type Consumer a = Pipe a C
- Control.Proxy.Pipe: type Pipe a b = Proxy () a () b
- Control.Proxy.Pipe: type Producer b = Pipe () b
- Control.Proxy.Prelude.IO: hGetLineD :: Handle -> y' -> Proxy x' x y' String IO r
- Control.Proxy.Prelude.IO: hGetLineU :: Handle -> y' -> Proxy String x y' y IO r
- Control.Proxy.Prelude.Kleisli: mapK :: (Monad m, MonadTrans t) => (a -> m b) -> (a -> t m b)
- Control.Proxy.Trans.Either: instance Control.MFunctor.MFunctor (p a' a b' b) => Control.MFunctor.MFunctor (Control.Proxy.Trans.Either.EitherP e p a' a b' b)
- Control.Proxy.Trans.Either: instance Control.Monad.IO.Class.MonadIO (p a' a b' b m) => Control.Monad.IO.Class.MonadIO (Control.Proxy.Trans.Either.EitherP e p a' a b' b m)
- Control.Proxy.Trans.Either: instance Control.Monad.Trans.Class.MonadTrans (p a' a b' b) => Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Trans.Either.EitherP e p a' a b' b)
- Control.Proxy.Trans.Either: instance Control.Proxy.Class.Channel p => Control.Proxy.Class.Channel (Control.Proxy.Trans.Either.EitherP e p)
- Control.Proxy.Trans.Either: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Applicative (Control.Proxy.Trans.Either.EitherP e p a' a b' b m)
- Control.Proxy.Trans.Either: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Functor (Control.Proxy.Trans.Either.EitherP e p a' a b' b m)
- Control.Proxy.Trans.Either: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Monad (Control.Proxy.Trans.Either.EitherP e p a' a b' b m)
- Control.Proxy.Trans.Either: instance GHC.Base.MonadPlus (p a' a b' b m) => GHC.Base.Alternative (Control.Proxy.Trans.Either.EitherP e p a' a b' b m)
- Control.Proxy.Trans.Either: instance GHC.Base.MonadPlus (p a' a b' b m) => GHC.Base.MonadPlus (Control.Proxy.Trans.Either.EitherP e p a' a b' b m)
- Control.Proxy.Trans.Identity: instance Control.MFunctor.MFunctor (p a' a b' b) => Control.MFunctor.MFunctor (Control.Proxy.Trans.Identity.IdentityP p a' a b' b)
- Control.Proxy.Trans.Identity: instance Control.Monad.IO.Class.MonadIO (p a' a b' b m) => Control.Monad.IO.Class.MonadIO (Control.Proxy.Trans.Identity.IdentityP p a' a b' b m)
- Control.Proxy.Trans.Identity: instance Control.Monad.Trans.Class.MonadTrans (p a' a b' b) => Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Trans.Identity.IdentityP p a' a b' b)
- Control.Proxy.Trans.Identity: instance Control.Proxy.Class.Channel p => Control.Proxy.Class.Channel (Control.Proxy.Trans.Identity.IdentityP p)
- Control.Proxy.Trans.Identity: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Applicative (Control.Proxy.Trans.Identity.IdentityP p a' a b' b m)
- Control.Proxy.Trans.Identity: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Functor (Control.Proxy.Trans.Identity.IdentityP p a' a b' b m)
- Control.Proxy.Trans.Identity: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Monad (Control.Proxy.Trans.Identity.IdentityP p a' a b' b m)
- Control.Proxy.Trans.Identity: instance GHC.Base.MonadPlus (p a' a b' b m) => GHC.Base.Alternative (Control.Proxy.Trans.Identity.IdentityP p a' a b' b m)
- Control.Proxy.Trans.Identity: instance GHC.Base.MonadPlus (p a' a b' b m) => GHC.Base.MonadPlus (Control.Proxy.Trans.Identity.IdentityP p a' a b' b m)
- Control.Proxy.Trans.Maybe: instance Control.MFunctor.MFunctor (p a' a b' b) => Control.MFunctor.MFunctor (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b)
- Control.Proxy.Trans.Maybe: instance Control.Monad.IO.Class.MonadIO (p a' a b' b m) => Control.Monad.IO.Class.MonadIO (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b m)
- Control.Proxy.Trans.Maybe: instance Control.Monad.Trans.Class.MonadTrans (p a' a b' b) => Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b)
- Control.Proxy.Trans.Maybe: instance Control.Proxy.Class.Channel p => Control.Proxy.Class.Channel (Control.Proxy.Trans.Maybe.MaybeP p)
- Control.Proxy.Trans.Maybe: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Alternative (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b m)
- Control.Proxy.Trans.Maybe: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Applicative (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b m)
- Control.Proxy.Trans.Maybe: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Functor (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b m)
- Control.Proxy.Trans.Maybe: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Monad (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b m)
- Control.Proxy.Trans.Maybe: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.MonadPlus (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b m)
- Control.Proxy.Trans.Reader: instance Control.MFunctor.MFunctor (p a' a b' b) => Control.MFunctor.MFunctor (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b)
- Control.Proxy.Trans.Reader: instance Control.Monad.IO.Class.MonadIO (p a' a b' b m) => Control.Monad.IO.Class.MonadIO (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b m)
- Control.Proxy.Trans.Reader: instance Control.Monad.Trans.Class.MonadTrans (p a' a b' b) => Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b)
- Control.Proxy.Trans.Reader: instance Control.Proxy.Class.Channel p => Control.Proxy.Class.Channel (Control.Proxy.Trans.Reader.ReaderP i p)
- Control.Proxy.Trans.Reader: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Applicative (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b m)
- Control.Proxy.Trans.Reader: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Functor (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b m)
- Control.Proxy.Trans.Reader: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Monad (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b m)
- Control.Proxy.Trans.Reader: instance GHC.Base.MonadPlus (p a' a b' b m) => GHC.Base.Alternative (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b m)
- Control.Proxy.Trans.Reader: instance GHC.Base.MonadPlus (p a' a b' b m) => GHC.Base.MonadPlus (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b m)
- Control.Proxy.Trans.State: instance Control.MFunctor.MFunctor (p a' a b' b) => Control.MFunctor.MFunctor (Control.Proxy.Trans.State.StateP s p a' a b' b)
- Control.Proxy.Trans.State: instance Control.Monad.IO.Class.MonadIO (p a' a b' b m) => Control.Monad.IO.Class.MonadIO (Control.Proxy.Trans.State.StateP s p a' a b' b m)
- Control.Proxy.Trans.State: instance Control.Monad.Trans.Class.MonadTrans (p a' a b' b) => Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Trans.State.StateP s p a' a b' b)
- Control.Proxy.Trans.State: instance Control.Proxy.Class.Channel p => Control.Proxy.Class.Channel (Control.Proxy.Trans.State.StateP s p)
- Control.Proxy.Trans.State: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Applicative (Control.Proxy.Trans.State.StateP s p a' a b' b m)
- Control.Proxy.Trans.State: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Functor (Control.Proxy.Trans.State.StateP s p a' a b' b m)
- Control.Proxy.Trans.State: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Monad (Control.Proxy.Trans.State.StateP s p a' a b' b m)
- Control.Proxy.Trans.State: instance GHC.Base.MonadPlus (p a' a b' b m) => GHC.Base.Alternative (Control.Proxy.Trans.State.StateP s p a' a b' b m)
- Control.Proxy.Trans.State: instance GHC.Base.MonadPlus (p a' a b' b m) => GHC.Base.MonadPlus (Control.Proxy.Trans.State.StateP s p a' a b' b m)
- Control.Proxy.Trans.Writer: instance Control.MFunctor.MFunctor (p a' a b' b) => Control.MFunctor.MFunctor (Control.Proxy.Trans.Writer.WriterP w p a' a b' b)
- Control.Proxy.Trans.Writer: instance Control.Monad.IO.Class.MonadIO (p a' a b' b m) => Control.Monad.IO.Class.MonadIO (Control.Proxy.Trans.Writer.WriterP w p a' a b' b m)
- Control.Proxy.Trans.Writer: instance Control.Monad.Trans.Class.MonadTrans (p a' a b' b) => Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Trans.Writer.WriterP w p a' a b' b)
- Control.Proxy.Trans.Writer: instance Control.Proxy.Class.Channel p => Control.Proxy.Class.Channel (Control.Proxy.Trans.Writer.WriterP w p)
- Control.Proxy.Trans.Writer: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Applicative (Control.Proxy.Trans.Writer.WriterP w p a' a b' b m)
- Control.Proxy.Trans.Writer: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Functor (Control.Proxy.Trans.Writer.WriterP w p a' a b' b m)
- Control.Proxy.Trans.Writer: instance GHC.Base.Monad (p a' a b' b m) => GHC.Base.Monad (Control.Proxy.Trans.Writer.WriterP w p a' a b' b m)
- Control.Proxy.Trans.Writer: instance GHC.Base.MonadPlus (p a' a b' b m) => GHC.Base.Alternative (Control.Proxy.Trans.Writer.WriterP w p a' a b' b m)
- Control.Proxy.Trans.Writer: instance GHC.Base.MonadPlus (p a' a b' b m) => GHC.Base.MonadPlus (Control.Proxy.Trans.Writer.WriterP w p a' a b' b m)
- Control.Proxy.Trans.Writer: instance GHC.Base.Monoid w => Control.Proxy.Trans.ProxyTrans (Control.Proxy.Trans.Writer.WriterP w)
- Data.Closed: data C
+ Control.MFunctor: hoist :: (MFunctor t, Monad m) => (forall a. m a -> n a) -> t m b -> t n b
+ Control.MFunctor: instance Control.MFunctor.MFunctor (Control.Monad.Trans.RWS.Lazy.RWST r w s)
+ Control.MFunctor: instance Control.MFunctor.MFunctor (Control.Monad.Trans.Reader.ReaderT r)
+ Control.MFunctor: instance Control.MFunctor.MFunctor (Control.Monad.Trans.State.Lazy.StateT s)
+ Control.MFunctor: instance Control.MFunctor.MFunctor (Control.Monad.Trans.State.Strict.StateT s)
+ Control.MFunctor: instance Control.MFunctor.MFunctor (Control.Monad.Trans.Writer.Lazy.WriterT w)
+ Control.MFunctor: instance Control.MFunctor.MFunctor (Control.Monad.Trans.Writer.Strict.WriterT w)
+ Control.MFunctor: instance Control.MFunctor.MFunctor Control.Monad.Trans.Identity.IdentityT
+ Control.MFunctor: instance Control.MFunctor.MFunctor Control.Monad.Trans.Maybe.MaybeT
+ Control.MFunctor: raise :: (Monad m, MFunctor t1, MonadTrans t2) => t1 m r -> t1 (t2 m) r
+ Control.PFunctor: class PFunctor (t :: (* -> * -> * -> * -> (* -> *) -> * -> *) -> * -> * -> * -> * -> (* -> *) -> * -> *)
+ Control.PFunctor: hoistP :: (PFunctor t, Monad m, Proxy p) => (forall a' a b' b r1. p a' a b' b m r1 -> q a' a b' b m r1) -> (t p a' a b' b m r2 -> t q a' a b' b m r2)
+ Control.PFunctor: raiseP :: (Monad m, Proxy p, PFunctor t1, ProxyTrans t2) => t1 p a' a b' b m r -> t1 (t2 p) a' a b' b m r
+ Control.Pipe: (<+<) :: (Monad m) => Pipe b c m r -> Pipe a b m r -> Pipe a c m r
+ Control.Pipe: (>+>) :: (Monad m) => Pipe a b m r -> Pipe b c m r -> Pipe a c m r
+ Control.Pipe: Await :: (a -> Pipe a b m r) -> Pipe a b m r
+ Control.Pipe: M :: (m (Pipe a b m r)) -> Pipe a b m r
+ Control.Pipe: PipeC :: Pipe a b m r -> PipeC m r a b
+ Control.Pipe: Pure :: r -> Pipe a b m r
+ Control.Pipe: Yield :: b -> (Pipe a b m r) -> Pipe a b m r
+ Control.Pipe: [unPipeC] :: PipeC m r a b -> Pipe a b m r
+ Control.Pipe: await :: Pipe a b m a
+ Control.Pipe: data Pipe a b m r
+ Control.Pipe: idP :: (Monad m) => Pipe a a m r
+ Control.Pipe: infixl 8 >+>
+ Control.Pipe: infixr 8 <+<
+ Control.Pipe: instance Control.Monad.Trans.Class.MonadTrans (Control.Pipe.Pipe a b)
+ Control.Pipe: instance GHC.Base.Monad m => Control.Category.Category (Control.Pipe.PipeC m r)
+ Control.Pipe: instance GHC.Base.Monad m => GHC.Base.Applicative (Control.Pipe.Pipe a b m)
+ Control.Pipe: instance GHC.Base.Monad m => GHC.Base.Functor (Control.Pipe.Pipe a b m)
+ Control.Pipe: instance GHC.Base.Monad m => GHC.Base.Monad (Control.Pipe.Pipe a b m)
+ Control.Pipe: newtype PipeC m r a b
+ Control.Pipe: pipe :: (Monad m) => (a -> b) -> Pipe a b m r
+ Control.Pipe: runPipe :: (Monad m) => Pipe () b m r -> m r
+ Control.Pipe: type Consumer a m r = Pipe a C m r
+ Control.Pipe: type Pipeline m r = Pipe () C m r
+ Control.Pipe: type Producer b m r = Pipe () b m r
+ Control.Pipe: yield :: b -> Pipe a b m ()
+ Control.Proxy.Class: (<~<) :: (Monad m, Proxy p) => (b -> p b' b c' c m r) -> (a -> p a' a b' b m r) -> (a -> p a' a c' c m r)
+ Control.Proxy.Class: (>~>) :: (Proxy p, Monad m) => (a -> p a' a b' b m r) -> (b -> p b' b c' c m r) -> (a -> p a' a c' c m r)
+ Control.Proxy.Class: (?>=) :: (Proxy p, Monad m) => p a' a b' b m r -> (r -> p a' a b' b m r') -> p a' a b' b m r'
+ Control.Proxy.Class: class (Proxy p) => MonadIOP p
+ Control.Proxy.Class: class (Proxy p) => MonadPlusP p
+ Control.Proxy.Class: class Proxy p
+ Control.Proxy.Class: coidT :: (Monad m, Proxy p) => a -> p a' a a' a m r
+ Control.Proxy.Class: hoist_P :: (Proxy p, Monad m) => (forall r. m r -> n r) -> (p a' a b' b m r' -> p a' a b' b n r')
+ Control.Proxy.Class: infixl 8 \<\
+ Control.Proxy.Class: infixr 7 <-<
+ Control.Proxy.Class: infixr 8 /</
+ Control.Proxy.Class: liftIO_P :: (MonadIOP p, MonadIO m) => IO r -> p a' a b' b m r
+ Control.Proxy.Class: lift_P :: (Proxy p, Monad m) => m r -> p a' a b' b m r
+ Control.Proxy.Class: mplus_P :: (MonadPlusP p, Monad m) => p a' a b' b m r -> p a' a b' b m r -> p a' a b' b m r
+ Control.Proxy.Class: mzero_P :: (MonadPlusP p, Monad m) => p a' a b' b m r
+ Control.Proxy.Class: return_P :: (Proxy p, Monad m) => r -> p a' a b' b m r
+ Control.Proxy.Core.Correct: Proxy :: m (ProxyF a' a b' b r (ProxyCorrect a' a b' b m r)) -> ProxyCorrect a' a b' b m r
+ Control.Proxy.Core.Correct: Pure :: r -> ProxyF a' a b' b r x
+ Control.Proxy.Core.Correct: Request :: a' -> (a -> x) -> ProxyF a' a b' b r x
+ Control.Proxy.Core.Correct: Respond :: b -> (b' -> x) -> ProxyF a' a b' b r x
+ Control.Proxy.Core.Correct: [unProxy] :: ProxyCorrect a' a b' b m r -> m (ProxyF a' a b' b r (ProxyCorrect a' a b' b m r))
+ Control.Proxy.Core.Correct: data ProxyCorrect a' a b' b m r
+ Control.Proxy.Core.Correct: data ProxyF a' a b' b r x
+ Control.Proxy.Core.Correct: instance Control.MFunctor.MFunctor (Control.Proxy.Core.Correct.ProxyCorrect a' a b' b)
+ Control.Proxy.Core.Correct: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Proxy.Core.Correct.ProxyCorrect a' a b' b m)
+ Control.Proxy.Core.Correct: instance Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Core.Correct.ProxyCorrect a' a b' b)
+ Control.Proxy.Core.Correct: instance Control.Proxy.Class.Interact Control.Proxy.Core.Correct.ProxyCorrect
+ Control.Proxy.Core.Correct: instance Control.Proxy.Class.MonadIOP Control.Proxy.Core.Correct.ProxyCorrect
+ Control.Proxy.Core.Correct: instance Control.Proxy.Class.Proxy Control.Proxy.Core.Correct.ProxyCorrect
+ Control.Proxy.Core.Correct: instance GHC.Base.Monad m => GHC.Base.Applicative (Control.Proxy.Core.Correct.ProxyCorrect a' a b' b m)
+ Control.Proxy.Core.Correct: instance GHC.Base.Monad m => GHC.Base.Functor (Control.Proxy.Core.Correct.ProxyCorrect a' a b' b m)
+ Control.Proxy.Core.Correct: instance GHC.Base.Monad m => GHC.Base.Monad (Control.Proxy.Core.Correct.ProxyCorrect a' a b' b m)
+ Control.Proxy.Core.Correct: runPipe :: (Monad m) => ProxyCorrect a' () () b m r -> m r
+ Control.Proxy.Core.Correct: runProxy :: (Monad m) => (() -> ProxyCorrect a' () () b m r) -> m r
+ Control.Proxy.Core.Correct: runProxyK :: (Monad m) => (() -> ProxyCorrect a' () () b m r) -> (() -> m r)
+ Control.Proxy.Core.Fast: M :: (m (ProxyFast a' a b' b m r)) -> ProxyFast a' a b' b m r
+ Control.Proxy.Core.Fast: Pure :: r -> ProxyFast a' a b' b m r
+ Control.Proxy.Core.Fast: Request :: a' -> (a -> ProxyFast a' a b' b m r) -> ProxyFast a' a b' b m r
+ Control.Proxy.Core.Fast: Respond :: b -> (b' -> ProxyFast a' a b' b m r) -> ProxyFast a' a b' b m r
+ Control.Proxy.Core.Fast: data ProxyFast a' a b' b m r
+ Control.Proxy.Core.Fast: instance Control.MFunctor.MFunctor (Control.Proxy.Core.Fast.ProxyFast a' a b' b)
+ Control.Proxy.Core.Fast: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Proxy.Core.Fast.ProxyFast a' a b' b m)
+ Control.Proxy.Core.Fast: instance Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Core.Fast.ProxyFast a' a b' b)
+ Control.Proxy.Core.Fast: instance Control.Proxy.Class.Interact Control.Proxy.Core.Fast.ProxyFast
+ Control.Proxy.Core.Fast: instance Control.Proxy.Class.MonadIOP Control.Proxy.Core.Fast.ProxyFast
+ Control.Proxy.Core.Fast: instance Control.Proxy.Class.Proxy Control.Proxy.Core.Fast.ProxyFast
+ Control.Proxy.Core.Fast: instance GHC.Base.Monad m => GHC.Base.Applicative (Control.Proxy.Core.Fast.ProxyFast a' a b' b m)
+ Control.Proxy.Core.Fast: instance GHC.Base.Monad m => GHC.Base.Functor (Control.Proxy.Core.Fast.ProxyFast a' a b' b m)
+ Control.Proxy.Core.Fast: instance GHC.Base.Monad m => GHC.Base.Monad (Control.Proxy.Core.Fast.ProxyFast a' a b' b m)
+ Control.Proxy.Core.Fast: observe :: (Monad m) => ProxyFast a' a b' b m r -> ProxyFast a' a b' b m r
+ Control.Proxy.Core.Fast: runPipe :: (Monad m) => ProxyFast a' () () b m r -> m r
+ Control.Proxy.Core.Fast: runProxy :: (Monad m) => (() -> ProxyFast a' () () b m r) -> m r
+ Control.Proxy.Core.Fast: runProxyK :: (Monad m) => (() -> ProxyFast a' () () b m r) -> (() -> m r)
+ Control.Proxy.Prelude.Base: allD :: (Monad m, Proxy p) => (a -> Bool) -> x -> p x a x a (WriterT All m) r
+ Control.Proxy.Prelude.Base: allD_ :: (Monad m, Proxy p) => (a -> Bool) -> x -> p x a x a (WriterT All m) ()
+ Control.Proxy.Prelude.Base: allU :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> p a' x a' x (WriterT All m) r
+ Control.Proxy.Prelude.Base: allU_ :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> p a' x a' x (WriterT All m) ()
+ Control.Proxy.Prelude.Base: anyD :: (Monad m, Proxy p) => (a -> Bool) -> x -> p x a x a (WriterT Any m) r
+ Control.Proxy.Prelude.Base: anyD_ :: (Monad m, Proxy p) => (a -> Bool) -> x -> p x a x a (WriterT Any m) ()
+ Control.Proxy.Prelude.Base: anyU :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> p a' x a' x (WriterT Any m) r
+ Control.Proxy.Prelude.Base: anyU_ :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> p a' x a' x (WriterT Any m) ()
+ Control.Proxy.Prelude.Base: foldD :: (Monad m, Proxy p, Monoid w) => (a -> w) -> x -> p x a x a (WriterT w m) r
+ Control.Proxy.Prelude.Base: foldU :: (Monad m, Proxy p, Monoid w) => (a' -> w) -> a' -> p a' x a' x (WriterT w m) r
+ Control.Proxy.Prelude.Base: foldlD' :: (Monad m, Proxy p) => (b -> a -> b) -> x -> p x a x a (StateT b m) r
+ Control.Proxy.Prelude.Base: foldlU' :: (Monad m, Proxy p) => (b -> a' -> b) -> a' -> p a' x a' x (StateT b m) r
+ Control.Proxy.Prelude.Base: foldrD :: (Monad m, Proxy p) => (a -> b -> b) -> x -> p x a x a (WriterT (Endo b) m) r
+ Control.Proxy.Prelude.Base: foldrU :: (Monad m, Proxy p) => (a' -> b -> b) -> a' -> p a' x a' x (WriterT (Endo b) m) r
+ Control.Proxy.Prelude.Base: headD :: (Monad m, Proxy p) => x -> p x a x a (WriterT (First a) m) r
+ Control.Proxy.Prelude.Base: headD_ :: (Monad m, Proxy p) => x -> p x a x a (WriterT (First a) m) ()
+ Control.Proxy.Prelude.Base: headU :: (Monad m, Proxy p) => a' -> p a' x a' x (WriterT (First a') m) r
+ Control.Proxy.Prelude.Base: headU_ :: (Monad m, Proxy p) => a' -> p a' x a' x (WriterT (First a') m) ()
+ Control.Proxy.Prelude.Base: lastD :: (Monad m, Proxy p) => x -> p x a x a (WriterT (Last a) m) r
+ Control.Proxy.Prelude.Base: lastU :: (Monad m, Proxy p) => a' -> p a' x a' x (WriterT (Last a') m) r
+ Control.Proxy.Prelude.Base: lengthD :: (Monad m, Proxy p) => x -> p x a x a (WriterT (Sum Int) m) r
+ Control.Proxy.Prelude.Base: lengthU :: (Monad m, Proxy p) => a' -> p a' x a' x (WriterT (Sum Int) m) r
+ Control.Proxy.Prelude.Base: mergeD :: (Monad m, Proxy p1, Proxy p2, Proxy p3) => () -> Consumer p1 a (Consumer p2 a (Producer p3 a m)) r
+ Control.Proxy.Prelude.Base: productD :: (Monad m, Proxy p, Num a) => x -> p x a x a (WriterT (Product a) m) r
+ Control.Proxy.Prelude.Base: productU :: (Monad m, Proxy p, Num a') => a' -> p a' x a' x (WriterT (Product a') m) r
+ Control.Proxy.Prelude.Base: sumD :: (Monad m, Proxy p, Num a) => x -> p x a x a (WriterT (Sum a) m) r
+ Control.Proxy.Prelude.Base: sumU :: (Monad m, Proxy p, Num a') => a' -> p a' x a' x (WriterT (Sum a') m) r
+ Control.Proxy.Prelude.Base: toListD :: (Monad m, Proxy p) => x -> p x a x a (WriterT [a] m) r
+ Control.Proxy.Prelude.Base: toListU :: (Monad m, Proxy p) => a' -> p a' x a' x (WriterT [a'] m) r
+ Control.Proxy.Prelude.Base: unitD :: (Monad m, Proxy p) => y' -> p x' x y' () m r
+ Control.Proxy.Prelude.Base: unitU :: (Monad m, Proxy p) => y' -> p () x y' y m r
+ Control.Proxy.Prelude.Base: useB :: (Monad m, Proxy p) => (a -> m r1) -> (a' -> m r2) -> a' -> p a' a a' a m r
+ Control.Proxy.Prelude.Base: useD :: (Monad m, Proxy p) => (a -> m r1) -> x -> p x a x a m r
+ Control.Proxy.Prelude.Base: useU :: (Monad m, Proxy p) => (a' -> m r2) -> a' -> p a' x a' x m r
+ Control.Proxy.Prelude.Base: zipD :: (Monad m, Proxy p1, Proxy p2, Proxy p3) => () -> Consumer p1 a (Consumer p2 b (Producer p3 (a, b) m)) r
+ Control.Proxy.Prelude.IO: hGetLineC :: (Proxy p) => Handle -> () -> CoProducer p String IO ()
+ Control.Proxy.Prelude.IO: hGetLineS :: (Proxy p) => Handle -> () -> Producer p String IO ()
+ Control.Proxy.Prelude.Kleisli: hoistK :: (Monad m, MFunctor t) => (forall a. m a -> n a) -> ((b' -> t m b) -> (b' -> t n b))
+ Control.Proxy.Prelude.Kleisli: liftK :: (Monad m, MonadTrans t) => (a -> m b) -> (a -> t m b)
+ Control.Proxy.Prelude.Kleisli: raiseK :: (Monad m, MFunctor t1, MonadTrans t2) => (q -> t1 m r) -> (q -> t1 (t2 m) r)
+ Control.Proxy.Synonym: data C
+ Control.Proxy.Synonym: type Client (p :: * -> * -> * -> * -> (* -> *) -> * -> *) a' a = p a' a () C
+ Control.Proxy.Synonym: type CoConsumer (p :: * -> * -> * -> * -> (* -> *) -> * -> *) b' = p C () b' ()
+ Control.Proxy.Synonym: type CoPipe (p :: * -> * -> * -> * -> (* -> *) -> * -> *) a' b' = p a' () b' ()
+ Control.Proxy.Synonym: type CoProducer (p :: * -> * -> * -> * -> (* -> *) -> * -> *) a' = p a' () () C
+ Control.Proxy.Synonym: type Consumer (p :: * -> * -> * -> * -> (* -> *) -> * -> *) a = p () a () C
+ Control.Proxy.Synonym: type Pipe (p :: * -> * -> * -> * -> (* -> *) -> * -> *) a b = p () a () b
+ Control.Proxy.Synonym: type Producer (p :: * -> * -> * -> * -> (* -> *) -> * -> *) b = p C () () b
+ Control.Proxy.Synonym: type Server (p :: * -> * -> * -> * -> (* -> *) -> * -> *) b' b = p C () b' b
+ Control.Proxy.Synonym: type Session (p :: * -> * -> * -> * -> (* -> *) -> * -> *) = p C () () C
+ Control.Proxy.Trans.Either: instance (Control.Proxy.Class.MonadIOP p, Control.Monad.IO.Class.MonadIO m) => Control.Monad.IO.Class.MonadIO (Control.Proxy.Trans.Either.EitherP e p a' a b' b m)
+ Control.Proxy.Trans.Either: instance (Control.Proxy.Class.MonadPlusP p, GHC.Base.Monad m) => GHC.Base.Alternative (Control.Proxy.Trans.Either.EitherP e p a' a b' b m)
+ Control.Proxy.Trans.Either: instance (Control.Proxy.Class.MonadPlusP p, GHC.Base.Monad m) => GHC.Base.MonadPlus (Control.Proxy.Trans.Either.EitherP e p a' a b' b m)
+ Control.Proxy.Trans.Either: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Applicative (Control.Proxy.Trans.Either.EitherP e p a' a b' b m)
+ Control.Proxy.Trans.Either: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Functor (Control.Proxy.Trans.Either.EitherP e p a' a b' b m)
+ Control.Proxy.Trans.Either: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Monad (Control.Proxy.Trans.Either.EitherP e p a' a b' b m)
+ Control.Proxy.Trans.Either: instance Control.PFunctor.PFunctor (Control.Proxy.Trans.Either.EitherP e)
+ Control.Proxy.Trans.Either: instance Control.Proxy.Class.MonadIOP p => Control.Proxy.Class.MonadIOP (Control.Proxy.Trans.Either.EitherP e p)
+ Control.Proxy.Trans.Either: instance Control.Proxy.Class.MonadPlusP p => Control.Proxy.Class.MonadPlusP (Control.Proxy.Trans.Either.EitherP e p)
+ Control.Proxy.Trans.Either: instance Control.Proxy.Class.Proxy p => Control.MFunctor.MFunctor (Control.Proxy.Trans.Either.EitherP e p a' a b' b)
+ Control.Proxy.Trans.Either: instance Control.Proxy.Class.Proxy p => Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Trans.Either.EitherP e p a' a b' b)
+ Control.Proxy.Trans.Either: instance Control.Proxy.Class.Proxy p => Control.Proxy.Class.Proxy (Control.Proxy.Trans.Either.EitherP e p)
+ Control.Proxy.Trans.Identity: identityK :: (q -> p a' a b' b m r) -> (q -> IdentityP p a' a b' b m r)
+ Control.Proxy.Trans.Identity: instance (Control.Proxy.Class.MonadIOP p, Control.Monad.IO.Class.MonadIO m) => Control.Monad.IO.Class.MonadIO (Control.Proxy.Trans.Identity.IdentityP p a' a b' b m)
+ Control.Proxy.Trans.Identity: instance (Control.Proxy.Class.MonadPlusP p, GHC.Base.Monad m) => GHC.Base.Alternative (Control.Proxy.Trans.Identity.IdentityP p a' a b' b m)
+ Control.Proxy.Trans.Identity: instance (Control.Proxy.Class.MonadPlusP p, GHC.Base.Monad m) => GHC.Base.MonadPlus (Control.Proxy.Trans.Identity.IdentityP p a' a b' b m)
+ Control.Proxy.Trans.Identity: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Applicative (Control.Proxy.Trans.Identity.IdentityP p a' a b' b m)
+ Control.Proxy.Trans.Identity: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Functor (Control.Proxy.Trans.Identity.IdentityP p a' a b' b m)
+ Control.Proxy.Trans.Identity: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Monad (Control.Proxy.Trans.Identity.IdentityP p a' a b' b m)
+ Control.Proxy.Trans.Identity: instance Control.PFunctor.PFunctor Control.Proxy.Trans.Identity.IdentityP
+ Control.Proxy.Trans.Identity: instance Control.Proxy.Class.MonadIOP p => Control.Proxy.Class.MonadIOP (Control.Proxy.Trans.Identity.IdentityP p)
+ Control.Proxy.Trans.Identity: instance Control.Proxy.Class.MonadPlusP p => Control.Proxy.Class.MonadPlusP (Control.Proxy.Trans.Identity.IdentityP p)
+ Control.Proxy.Trans.Identity: instance Control.Proxy.Class.Proxy p => Control.MFunctor.MFunctor (Control.Proxy.Trans.Identity.IdentityP p a' a b' b)
+ Control.Proxy.Trans.Identity: instance Control.Proxy.Class.Proxy p => Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Trans.Identity.IdentityP p a' a b' b)
+ Control.Proxy.Trans.Identity: instance Control.Proxy.Class.Proxy p => Control.Proxy.Class.Proxy (Control.Proxy.Trans.Identity.IdentityP p)
+ Control.Proxy.Trans.Maybe: instance (Control.Proxy.Class.MonadIOP p, Control.Monad.IO.Class.MonadIO m) => Control.Monad.IO.Class.MonadIO (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b m)
+ Control.Proxy.Trans.Maybe: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Alternative (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b m)
+ Control.Proxy.Trans.Maybe: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Applicative (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b m)
+ Control.Proxy.Trans.Maybe: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Functor (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b m)
+ Control.Proxy.Trans.Maybe: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Monad (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b m)
+ Control.Proxy.Trans.Maybe: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.MonadPlus (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b m)
+ Control.Proxy.Trans.Maybe: instance Control.PFunctor.PFunctor Control.Proxy.Trans.Maybe.MaybeP
+ Control.Proxy.Trans.Maybe: instance Control.Proxy.Class.MonadIOP p => Control.Proxy.Class.MonadIOP (Control.Proxy.Trans.Maybe.MaybeP p)
+ Control.Proxy.Trans.Maybe: instance Control.Proxy.Class.Proxy p => Control.MFunctor.MFunctor (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b)
+ Control.Proxy.Trans.Maybe: instance Control.Proxy.Class.Proxy p => Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Trans.Maybe.MaybeP p a' a b' b)
+ Control.Proxy.Trans.Maybe: instance Control.Proxy.Class.Proxy p => Control.Proxy.Class.MonadPlusP (Control.Proxy.Trans.Maybe.MaybeP p)
+ Control.Proxy.Trans.Maybe: instance Control.Proxy.Class.Proxy p => Control.Proxy.Class.Proxy (Control.Proxy.Trans.Maybe.MaybeP p)
+ Control.Proxy.Trans.Reader: instance (Control.Proxy.Class.MonadIOP p, Control.Monad.IO.Class.MonadIO m) => Control.Monad.IO.Class.MonadIO (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b m)
+ Control.Proxy.Trans.Reader: instance (Control.Proxy.Class.MonadPlusP p, GHC.Base.Monad m) => GHC.Base.Alternative (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b m)
+ Control.Proxy.Trans.Reader: instance (Control.Proxy.Class.MonadPlusP p, GHC.Base.Monad m) => GHC.Base.MonadPlus (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b m)
+ Control.Proxy.Trans.Reader: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Applicative (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b m)
+ Control.Proxy.Trans.Reader: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Functor (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b m)
+ Control.Proxy.Trans.Reader: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Monad (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b m)
+ Control.Proxy.Trans.Reader: instance Control.PFunctor.PFunctor (Control.Proxy.Trans.Reader.ReaderP i)
+ Control.Proxy.Trans.Reader: instance Control.Proxy.Class.MonadIOP p => Control.Proxy.Class.MonadIOP (Control.Proxy.Trans.Reader.ReaderP i p)
+ Control.Proxy.Trans.Reader: instance Control.Proxy.Class.MonadPlusP p => Control.Proxy.Class.MonadPlusP (Control.Proxy.Trans.Reader.ReaderP i p)
+ Control.Proxy.Trans.Reader: instance Control.Proxy.Class.Proxy p => Control.MFunctor.MFunctor (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b)
+ Control.Proxy.Trans.Reader: instance Control.Proxy.Class.Proxy p => Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Trans.Reader.ReaderP i p a' a b' b)
+ Control.Proxy.Trans.Reader: instance Control.Proxy.Class.Proxy p => Control.Proxy.Class.Proxy (Control.Proxy.Trans.Reader.ReaderP i p)
+ Control.Proxy.Trans.State: instance (Control.Proxy.Class.MonadIOP p, Control.Monad.IO.Class.MonadIO m) => Control.Monad.IO.Class.MonadIO (Control.Proxy.Trans.State.StateP s p a' a b' b m)
+ Control.Proxy.Trans.State: instance (Control.Proxy.Class.MonadPlusP p, GHC.Base.Monad m) => GHC.Base.Alternative (Control.Proxy.Trans.State.StateP s p a' a b' b m)
+ Control.Proxy.Trans.State: instance (Control.Proxy.Class.MonadPlusP p, GHC.Base.Monad m) => GHC.Base.MonadPlus (Control.Proxy.Trans.State.StateP s p a' a b' b m)
+ Control.Proxy.Trans.State: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Applicative (Control.Proxy.Trans.State.StateP s p a' a b' b m)
+ Control.Proxy.Trans.State: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Functor (Control.Proxy.Trans.State.StateP s p a' a b' b m)
+ Control.Proxy.Trans.State: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Monad (Control.Proxy.Trans.State.StateP s p a' a b' b m)
+ Control.Proxy.Trans.State: instance Control.PFunctor.PFunctor (Control.Proxy.Trans.State.StateP s)
+ Control.Proxy.Trans.State: instance Control.Proxy.Class.MonadIOP p => Control.Proxy.Class.MonadIOP (Control.Proxy.Trans.State.StateP s p)
+ Control.Proxy.Trans.State: instance Control.Proxy.Class.MonadPlusP p => Control.Proxy.Class.MonadPlusP (Control.Proxy.Trans.State.StateP s p)
+ Control.Proxy.Trans.State: instance Control.Proxy.Class.Proxy p => Control.MFunctor.MFunctor (Control.Proxy.Trans.State.StateP s p a' a b' b)
+ Control.Proxy.Trans.State: instance Control.Proxy.Class.Proxy p => Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Trans.State.StateP s p a' a b' b)
+ Control.Proxy.Trans.State: instance Control.Proxy.Class.Proxy p => Control.Proxy.Class.Proxy (Control.Proxy.Trans.State.StateP s p)
+ Control.Proxy.Trans.Writer: instance (Control.Proxy.Class.MonadIOP p, Control.Monad.IO.Class.MonadIO m) => Control.Monad.IO.Class.MonadIO (Control.Proxy.Trans.Writer.WriterP w p a' a b' b m)
+ Control.Proxy.Trans.Writer: instance (Control.Proxy.Class.MonadPlusP p, GHC.Base.Monad m) => GHC.Base.Alternative (Control.Proxy.Trans.Writer.WriterP w p a' a b' b m)
+ Control.Proxy.Trans.Writer: instance (Control.Proxy.Class.MonadPlusP p, GHC.Base.Monad m) => GHC.Base.MonadPlus (Control.Proxy.Trans.Writer.WriterP w p a' a b' b m)
+ Control.Proxy.Trans.Writer: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Applicative (Control.Proxy.Trans.Writer.WriterP w p a' a b' b m)
+ Control.Proxy.Trans.Writer: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Functor (Control.Proxy.Trans.Writer.WriterP w p a' a b' b m)
+ Control.Proxy.Trans.Writer: instance (Control.Proxy.Class.Proxy p, GHC.Base.Monad m) => GHC.Base.Monad (Control.Proxy.Trans.Writer.WriterP w p a' a b' b m)
+ Control.Proxy.Trans.Writer: instance Control.PFunctor.PFunctor (Control.Proxy.Trans.Writer.WriterP w)
+ Control.Proxy.Trans.Writer: instance Control.Proxy.Class.MonadIOP p => Control.Proxy.Class.MonadIOP (Control.Proxy.Trans.Writer.WriterP w p)
+ Control.Proxy.Trans.Writer: instance Control.Proxy.Class.MonadPlusP p => Control.Proxy.Class.MonadPlusP (Control.Proxy.Trans.Writer.WriterP w p)
+ Control.Proxy.Trans.Writer: instance Control.Proxy.Class.Proxy p => Control.MFunctor.MFunctor (Control.Proxy.Trans.Writer.WriterP w p a' a b' b)
+ Control.Proxy.Trans.Writer: instance Control.Proxy.Class.Proxy p => Control.Monad.Trans.Class.MonadTrans (Control.Proxy.Trans.Writer.WriterP w p a' a b' b)
+ Control.Proxy.Trans.Writer: instance Control.Proxy.Class.Proxy p => Control.Proxy.Class.Proxy (Control.Proxy.Trans.Writer.WriterP w p)
+ Control.Proxy.Trans.Writer: instance Control.Proxy.Trans.ProxyTrans (Control.Proxy.Trans.Writer.WriterP w)
- Control.Proxy.Class: (/</) :: (Interact p, Monad m) => (c' -> p b' b x' x m c) -> (b' -> p a' a x' x m b) -> (c' -> p a' a x' x m c)
+ Control.Proxy.Class: (/</) :: (Monad m, Interact p) => (c' -> p b' b x' x m c) -> (b' -> p a' a x' x m b) -> (c' -> p a' a x' x m c)
- Control.Proxy.Class: (<-<) :: (Channel p, Monad m) => (c' -> p b' b c' c m r) -> (b' -> p a' a b' b m r) -> (c' -> p a' a c' c m r)
+ Control.Proxy.Class: (<-<) :: (Monad m, Proxy p) => (c' -> p b' b c' c m r) -> (b' -> p a' a b' b m r) -> (c' -> p a' a c' c m r)
- Control.Proxy.Class: (>->) :: (Channel p, Monad m) => (b' -> p a' a b' b m r) -> (c' -> p b' b c' c m r) -> (c' -> p a' a c' c m r)
+ Control.Proxy.Class: (>->) :: (Proxy p, Monad m) => (b' -> p a' a b' b m r) -> (c' -> p b' b c' c m r) -> (c' -> p a' a c' c m r)
- Control.Proxy.Class: (\<\) :: (Interact p, Monad m) => (b -> p x' x c' c m b') -> (a -> p x' x b' b m a') -> (a -> p x' x c' c m a')
+ Control.Proxy.Class: (\<\) :: (Monad m, Interact p) => (b -> p x' x c' c m b') -> (a -> p x' x b' b m a') -> (a -> p x' x c' c m a')
- Control.Proxy.Class: class Interact p where p1 \>\ p2 = p2 /</ p1 p1 /</ p2 = p2 \>\ p1 p1 />/ p2 = p2 \<\ p1 p1 \<\ p2 = p2 />/ p1
+ Control.Proxy.Class: class Interact p
- Control.Proxy.Class: idT :: (Channel p, Monad m) => a' -> p a' a a' a m r
+ Control.Proxy.Class: idT :: (Monad m, Proxy p) => a' -> p a' a a' a m r
- Control.Proxy.Class: request :: (Interact p, Monad m) => a' -> p a' a x' x m a
+ Control.Proxy.Class: request :: (Proxy p, Monad m) => a' -> p a' a b' b m a
- Control.Proxy.Class: respond :: (Interact p, Monad m) => a -> p x' x a' a m a'
+ Control.Proxy.Class: respond :: (Proxy p, Monad m) => b -> p a' a b' b m b'
- Control.Proxy.Pipe: (<+<) :: (Monad m) => Pipe b c m r -> Pipe a b m r -> Pipe a c m r
+ Control.Proxy.Pipe: (<+<) :: (Monad m, Proxy p) => Pipe p b c m r -> Pipe p a b m r -> Pipe p a c m r
- Control.Proxy.Pipe: (>+>) :: (Monad m) => Pipe a b m r -> Pipe b c m r -> Pipe a c m r
+ Control.Proxy.Pipe: (>+>) :: (Monad m, Proxy p) => Pipe p a b m r -> Pipe p b c m r -> Pipe p a c m r
- Control.Proxy.Pipe: await :: (Monad m) => Pipe a b m a
+ Control.Proxy.Pipe: await :: (Monad m, Proxy p) => Pipe p a b m a
- Control.Proxy.Pipe: idP :: (Monad m) => Pipe a a m r
+ Control.Proxy.Pipe: idP :: (Monad m, Proxy p) => Pipe p a a m r
- Control.Proxy.Pipe: pipe :: (Monad m) => (a -> b) -> Pipe a b m r
+ Control.Proxy.Pipe: pipe :: (Monad m, Proxy p) => (a -> b) -> Pipe p a b m r
- Control.Proxy.Pipe: type Pipeline = Pipe () C
+ Control.Proxy.Pipe: type Pipeline (p :: * -> * -> * -> * -> (* -> *) -> * -> *) = p C () () C
- Control.Proxy.Pipe: yield :: (Monad m) => b -> Pipe a b m ()
+ Control.Proxy.Pipe: yield :: (Monad m, Proxy p) => b -> p a' a b' b m ()
- Control.Proxy.Prelude.Base: dropD :: (Monad m) => Int -> () -> Proxy () a () a m r
+ Control.Proxy.Prelude.Base: dropD :: (Monad m, Proxy p) => Int -> () -> Pipe p a a m r
- Control.Proxy.Prelude.Base: dropU :: (Monad m) => Int -> a' -> Proxy a' () a' () m r
+ Control.Proxy.Prelude.Base: dropU :: (Monad m, Proxy p) => Int -> a' -> CoPipe p a' a' m r
- Control.Proxy.Prelude.Base: dropWhileD :: (Monad m) => (a -> Bool) -> () -> Proxy () a () a m r
+ Control.Proxy.Prelude.Base: dropWhileD :: (Monad m, Proxy p) => (a -> Bool) -> () -> Pipe p a a m r
- Control.Proxy.Prelude.Base: dropWhileU :: (Monad m) => (a' -> Bool) -> a' -> Proxy a' () a' () m r
+ Control.Proxy.Prelude.Base: dropWhileU :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> CoPipe p a' a' m r
- Control.Proxy.Prelude.Base: enumFromC :: (Enum a, Monad m) => a -> y' -> Proxy a x y' y m r
+ Control.Proxy.Prelude.Base: enumFromC :: (Enum a', Monad m, Proxy p) => a' -> () -> CoProducer p a' m r
- Control.Proxy.Prelude.Base: enumFromS :: (Enum a, Monad m) => a -> y' -> Proxy x' x y' a m r
+ Control.Proxy.Prelude.Base: enumFromS :: (Enum b, Monad m, Proxy p) => b -> () -> Producer p b m r
- Control.Proxy.Prelude.Base: enumFromToC :: (Enum a, Ord a, Monad m) => a -> a -> y' -> Proxy a x y' y m ()
+ Control.Proxy.Prelude.Base: enumFromToC :: (Enum a', Ord a', Monad m, Proxy p) => a' -> a' -> () -> CoProducer p a' m ()
- Control.Proxy.Prelude.Base: enumFromToS :: (Enum a, Ord a, Monad m) => a -> a -> y' -> Proxy x' x y' a m ()
+ Control.Proxy.Prelude.Base: enumFromToS :: (Enum b, Ord b, Monad m, Proxy p) => b -> b -> () -> Producer p b m ()
- Control.Proxy.Prelude.Base: execB :: (Monad m) => m () -> m () -> a' -> Proxy a' a a' a m r
+ Control.Proxy.Prelude.Base: execB :: (Monad m, Proxy p) => m r1 -> m r2 -> a' -> p a' a a' a m r
- Control.Proxy.Prelude.Base: execD :: (Monad m) => m () -> a' -> Proxy a' a a' a m r
+ Control.Proxy.Prelude.Base: execD :: (Monad m, Proxy p) => m r1 -> a' -> p a' a a' a m r
- Control.Proxy.Prelude.Base: execU :: (Monad m) => m () -> a' -> Proxy a' a a' a m r
+ Control.Proxy.Prelude.Base: execU :: (Monad m, Proxy p) => m r2 -> a' -> p a' a a' a m r
- Control.Proxy.Prelude.Base: filterD :: (Monad m) => (a -> Bool) -> () -> Proxy () a () a m r
+ Control.Proxy.Prelude.Base: filterD :: (Monad m, Proxy p) => (a -> Bool) -> () -> Pipe p a a m r
- Control.Proxy.Prelude.Base: filterU :: (Monad m) => (a' -> Bool) -> a' -> Proxy a' () a' () m r
+ Control.Proxy.Prelude.Base: filterU :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> CoPipe p a' a' m r
- Control.Proxy.Prelude.Base: fromListC :: (Monad m) => [a] -> () -> Proxy a x () y m ()
+ Control.Proxy.Prelude.Base: fromListC :: (Monad m, Proxy p) => [a'] -> () -> CoProducer p a' m ()
- Control.Proxy.Prelude.Base: fromListS :: (Monad m) => [a] -> () -> Proxy x' x () a m ()
+ Control.Proxy.Prelude.Base: fromListS :: (Monad m, Proxy p) => [b] -> () -> Producer p b m ()
- Control.Proxy.Prelude.Base: mapB :: (Monad m) => (a -> b) -> (b' -> a') -> b' -> Proxy a' a b' b m r
+ Control.Proxy.Prelude.Base: mapB :: (Monad m, Proxy p) => (a -> b) -> (b' -> a') -> b' -> p a' a b' b m r
- Control.Proxy.Prelude.Base: mapD :: (Monad m) => (a -> b) -> x -> Proxy x a x b m r
+ Control.Proxy.Prelude.Base: mapD :: (Monad m, Proxy p) => (a -> b) -> x -> p x a x b m r
- Control.Proxy.Prelude.Base: mapMB :: (Monad m) => (a -> m b) -> (b' -> m a') -> b' -> Proxy a' a b' b m r
+ Control.Proxy.Prelude.Base: mapMB :: (Monad m, Proxy p) => (a -> m b) -> (b' -> m a') -> b' -> p a' a b' b m r
- Control.Proxy.Prelude.Base: mapMD :: (Monad m) => (a -> m b) -> x -> Proxy x a x b m r
+ Control.Proxy.Prelude.Base: mapMD :: (Monad m, Proxy p) => (a -> m b) -> x -> p x a x b m r
- Control.Proxy.Prelude.Base: mapMU :: (Monad m) => (b' -> m a') -> b' -> Proxy a' x b' x m r
+ Control.Proxy.Prelude.Base: mapMU :: (Monad m, Proxy p) => (b' -> m a') -> b' -> p a' x b' x m r
- Control.Proxy.Prelude.Base: mapU :: (Monad m) => (b' -> a') -> b' -> Proxy a' x b' x m r
+ Control.Proxy.Prelude.Base: mapU :: (Monad m, Proxy p) => (b' -> a') -> b' -> p a' x b' x m r
- Control.Proxy.Prelude.Base: takeB :: (Monad m) => Int -> a' -> Proxy a' a a' a m a'
+ Control.Proxy.Prelude.Base: takeB :: (Monad m, Proxy p) => Int -> a' -> p a' a a' a m a'
- Control.Proxy.Prelude.Base: takeB_ :: (Monad m) => Int -> a' -> Proxy a' a a' a m ()
+ Control.Proxy.Prelude.Base: takeB_ :: (Monad m, Proxy p) => Int -> a' -> p a' a a' a m ()
- Control.Proxy.Prelude.Base: takeWhileD :: (Monad m) => (a -> Bool) -> a' -> Proxy a' a a' a m ()
+ Control.Proxy.Prelude.Base: takeWhileD :: (Monad m, Proxy p) => (a -> Bool) -> a' -> p a' a a' a m ()
- Control.Proxy.Prelude.Base: takeWhileU :: (Monad m) => (a' -> Bool) -> a' -> Proxy a' a a' a m ()
+ Control.Proxy.Prelude.Base: takeWhileU :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> p a' a a' a m ()
- Control.Proxy.Prelude.IO: getLineC :: y' -> Proxy String x y' y IO r
+ Control.Proxy.Prelude.IO: getLineC :: (Proxy p) => () -> CoProducer p String IO r
- Control.Proxy.Prelude.IO: getLineS :: y' -> Proxy x' x y' String IO r
+ Control.Proxy.Prelude.IO: getLineS :: (Proxy p) => () -> Producer p String IO r
- Control.Proxy.Prelude.IO: hPrintB :: (Show a, Show a') => Handle -> a' -> Proxy a' a a' a IO r
+ Control.Proxy.Prelude.IO: hPrintB :: (Show a, Show a', Proxy p) => Handle -> a' -> p a' a a' a IO r
- Control.Proxy.Prelude.IO: hPrintD :: (Show a) => Handle -> x -> Proxy x a x a IO r
+ Control.Proxy.Prelude.IO: hPrintD :: (Show a, Proxy p) => Handle -> x -> p x a x a IO r
- Control.Proxy.Prelude.IO: hPrintU :: (Show a') => Handle -> a' -> Proxy a' x a' x IO r
+ Control.Proxy.Prelude.IO: hPrintU :: (Show a', Proxy p) => Handle -> a' -> p a' x a' x IO r
- Control.Proxy.Prelude.IO: hPutStrLnB :: Handle -> String -> Proxy String String String String IO r
+ Control.Proxy.Prelude.IO: hPutStrLnB :: (Proxy p) => Handle -> String -> p String String String String IO r
- Control.Proxy.Prelude.IO: hPutStrLnD :: Handle -> x -> Proxy x String x String IO r
+ Control.Proxy.Prelude.IO: hPutStrLnD :: (Proxy p) => Handle -> x -> p x String x String IO r
- Control.Proxy.Prelude.IO: hPutStrLnU :: Handle -> String -> Proxy String x String x IO r
+ Control.Proxy.Prelude.IO: hPutStrLnU :: (Proxy p) => Handle -> String -> p String x String x IO r
- Control.Proxy.Prelude.IO: printB :: (Show a, Show a') => a' -> Proxy a' a a' a IO r
+ Control.Proxy.Prelude.IO: printB :: (Show a', Show a, Proxy p) => a' -> p a' a a' a IO r
- Control.Proxy.Prelude.IO: printD :: (Show a) => x -> Proxy x a x a IO r
+ Control.Proxy.Prelude.IO: printD :: (Show a, Proxy p) => x -> p x a x a IO r
- Control.Proxy.Prelude.IO: printU :: (Show a') => a' -> Proxy a' x a' x IO r
+ Control.Proxy.Prelude.IO: printU :: (Show a', Proxy p) => a' -> p a' x a' x IO r
- Control.Proxy.Prelude.IO: promptC :: y' -> Proxy String String y' y IO r
+ Control.Proxy.Prelude.IO: promptC :: (Proxy p) => () -> Client p String String IO r
- Control.Proxy.Prelude.IO: promptS :: String -> Proxy x' x String String IO r
+ Control.Proxy.Prelude.IO: promptS :: (Proxy p) => String -> Server p String String IO r
- Control.Proxy.Prelude.IO: putStrLnB :: String -> Proxy String String String String IO r
+ Control.Proxy.Prelude.IO: putStrLnB :: (Proxy p) => String -> p String String String String IO r
- Control.Proxy.Prelude.IO: putStrLnD :: x -> Proxy x String x String IO r
+ Control.Proxy.Prelude.IO: putStrLnD :: (Proxy p) => x -> p x String x String IO r
- Control.Proxy.Prelude.IO: putStrLnU :: String -> Proxy String x String x IO r
+ Control.Proxy.Prelude.IO: putStrLnU :: (Proxy p) => String -> p String x String x IO r
- Control.Proxy.Prelude.IO: readLnC :: (Read a) => y' -> Proxy a x y' y IO r
+ Control.Proxy.Prelude.IO: readLnC :: (Read a', Proxy p) => () -> CoProducer p a' IO r
- Control.Proxy.Prelude.IO: readLnS :: (Read a) => y' -> Proxy x' x y' a IO r
+ Control.Proxy.Prelude.IO: readLnS :: (Read b, Proxy p) => () -> Producer p b IO r
- Control.Proxy.Trans: class ProxyTrans t where liftP f = mapP (\ () -> f) () mapP = (liftP .)
+ Control.Proxy.Trans: class ProxyTrans t
- Control.Proxy.Trans: liftP :: (ProxyTrans t, Monad (p b c d e m), Channel p) => p b c d e m r -> t p b c d e m r
+ Control.Proxy.Trans: liftP :: (ProxyTrans t, Monad m, Proxy p) => p a' a b' b m r -> t p a' a b' b m r
- Control.Proxy.Trans: mapP :: (ProxyTrans t, Monad (p b c d e m), Channel p) => (a -> p b c d e m r) -> (a -> t p b c d e m r)
+ Control.Proxy.Trans: mapP :: (Monad m, Proxy p, ProxyTrans t) => (q -> p a' a b' b m r) -> (q -> t p a' a b' b m r)
- Control.Proxy.Trans.Either: catch :: (Monad (p a' a b' b m)) => EitherP e p a' a b' b m r -> (e -> EitherP f p a' a b' b m r) -> EitherP f p a' a b' b m r
+ Control.Proxy.Trans.Either: catch :: (Monad m, Proxy p) => EitherP e p a' a b' b m r -> (e -> EitherP f p a' a b' b m r) -> EitherP f p a' a b' b m r
- Control.Proxy.Trans.Either: handle :: (Monad (p a' a b' b m)) => (e -> EitherP f p a' a b' b m r) -> EitherP e p a' a b' b m r -> EitherP f p a' a b' b m r
+ Control.Proxy.Trans.Either: handle :: (Monad m, Proxy p) => (e -> EitherP f p a' a b' b m r) -> EitherP e p a' a b' b m r -> EitherP f p a' a b' b m r
- Control.Proxy.Trans.Either: left :: (Monad (p a' a b' b m)) => e -> EitherP e p a' a b' b m r
+ Control.Proxy.Trans.Either: left :: (Monad m, Proxy p) => e -> EitherP e p a' a b' b m r
- Control.Proxy.Trans.Either: right :: (Monad (p a' a b' b m)) => r -> EitherP e p a' a b' b m r
+ Control.Proxy.Trans.Either: right :: (Monad m, Proxy p) => r -> EitherP e p a' a b' b m r
- Control.Proxy.Trans.Either: throw :: (Monad (p a' a b' b m)) => e -> EitherP e p a' a b' b m r
+ Control.Proxy.Trans.Either: throw :: (Monad m, Proxy p) => e -> EitherP e p a' a b' b m r
- Control.Proxy.Trans.Maybe: just :: (Monad (p a' a b' b m)) => r -> MaybeP p a' a b' b m r
+ Control.Proxy.Trans.Maybe: just :: (Monad m, Proxy p) => r -> MaybeP p a' a b' b m r
- Control.Proxy.Trans.Maybe: nothing :: (Monad (p a' a b' b m)) => MaybeP p a' a b' b m r
+ Control.Proxy.Trans.Maybe: nothing :: (Monad m, Proxy p) => MaybeP p a' a b' b m r
- Control.Proxy.Trans.Reader: ask :: (Monad (p a' a b' b m)) => ReaderP i p a' a b' b m i
+ Control.Proxy.Trans.Reader: ask :: (Proxy p, Monad m) => ReaderP i p a' a b' b m i
- Control.Proxy.Trans.Reader: asks :: (Monad (p a' a b' b m)) => (i -> r) -> ReaderP i p a' a b' b m r
+ Control.Proxy.Trans.Reader: asks :: (Proxy p, Monad m) => (i -> r) -> ReaderP i p a' a b' b m r
- Control.Proxy.Trans.Reader: local :: (Monad (p a' a b' b m)) => (i -> i) -> ReaderP i p a' a b' b m r -> ReaderP i p a' a b' b m r
+ Control.Proxy.Trans.Reader: local :: (i -> i) -> ReaderP i p a' a b' b m r -> ReaderP i p a' a b' b m r
- Control.Proxy.Trans.Reader: withReaderP :: (Monad (p a' a b' b m)) => (j -> i) -> ReaderP i p a' a b' b m r -> ReaderP j p a' a b' b m r
+ Control.Proxy.Trans.Reader: withReaderP :: (j -> i) -> ReaderP i p a' a b' b m r -> ReaderP j p a' a b' b m r
- Control.Proxy.Trans.State: evalStateK :: (Monad (p a' a b' b m)) => s -> (q -> StateP s p a' a b' b m r) -> (q -> p a' a b' b m r)
+ Control.Proxy.Trans.State: evalStateK :: (Proxy p, Monad m) => s -> (q -> StateP s p a' a b' b m r) -> (q -> p a' a b' b m r)
- Control.Proxy.Trans.State: evalStateP :: (Monad (p a' a b' b m)) => s -> StateP s p a' a b' b m r -> p a' a b' b m r
+ Control.Proxy.Trans.State: evalStateP :: (Proxy p, Monad m) => s -> StateP s p a' a b' b m r -> p a' a b' b m r
- Control.Proxy.Trans.State: execStateK :: (Monad (p a' a b' b m)) => s -> (q -> StateP s p a' a b' b m r) -> (q -> p a' a b' b m s)
+ Control.Proxy.Trans.State: execStateK :: (Proxy p, Monad m) => s -> (q -> StateP s p a' a b' b m r) -> (q -> p a' a b' b m s)
- Control.Proxy.Trans.State: execStateP :: (Monad (p a' a b' b m)) => s -> StateP s p a' a b' b m r -> p a' a b' b m s
+ Control.Proxy.Trans.State: execStateP :: (Proxy p, Monad m) => s -> StateP s p a' a b' b m r -> p a' a b' b m s
- Control.Proxy.Trans.State: get :: (Monad (p a' a b' b m)) => StateP s p a' a b' b m s
+ Control.Proxy.Trans.State: get :: (Proxy p, Monad m) => StateP s p a' a b' b m s
- Control.Proxy.Trans.State: gets :: (Monad (p a' a b' b m)) => (s -> r) -> StateP s p a' a b' b m r
+ Control.Proxy.Trans.State: gets :: (Proxy p, Monad m) => (s -> r) -> StateP s p a' a b' b m r
- Control.Proxy.Trans.State: modify :: (Monad (p a' a b' b m)) => (s -> s) -> StateP s p a' a b' b m ()
+ Control.Proxy.Trans.State: modify :: (Proxy p, Monad m) => (s -> s) -> StateP s p a' a b' b m ()
- Control.Proxy.Trans.State: put :: (Monad (p a' a b' b m)) => s -> StateP s p a' a b' b m ()
+ Control.Proxy.Trans.State: put :: (Proxy p, Monad m) => s -> StateP s p a' a b' b m ()
- Control.Proxy.Trans.Writer: censor :: (Monad (p a' a b' b m), Monoid w) => (w -> w) -> WriterP w p a' a b' b m r -> WriterP w p a' a b' b m r
+ Control.Proxy.Trans.Writer: censor :: (Proxy p, Monad m, Monoid w) => (w -> w) -> WriterP w p a' a b' b m r -> WriterP w p a' a b' b m r
- Control.Proxy.Trans.Writer: execWriterK :: (Monad (p a' a b' b m), Monoid w) => (q -> WriterP w p a' a b' b m r) -> (q -> p a' a b' b m w)
+ Control.Proxy.Trans.Writer: execWriterK :: (Proxy p, Monad m, Monoid w) => (q -> WriterP w p a' a b' b m r) -> (q -> p a' a b' b m w)
- Control.Proxy.Trans.Writer: execWriterP :: (Monad (p a' a b' b m), Monoid w) => WriterP w p a' a b' b m r -> p a' a b' b m w
+ Control.Proxy.Trans.Writer: execWriterP :: (Proxy p, Monad m, Monoid w) => WriterP w p a' a b' b m r -> p a' a b' b m w
- Control.Proxy.Trans.Writer: tell :: (Monad (p a' a b' b m), Monoid w) => w -> WriterP w p a' a b' b m ()
+ Control.Proxy.Trans.Writer: tell :: (Proxy p, Monad m, Monoid w) => w -> WriterP w p a' a b' b m ()

Files

− Control/Frame.hs
@@ -1,473 +0,0 @@-{-|-    'Frame's extend 'Pipe's with:--    * The ability to fold input--    * Prompt and deterministic finalization--    'Frame's differ from 'Pipe's because they form restricted monads rather than-    forming ordinary monads.  This means you must rebind @do@ notation to use-    restricted monads from the @index-core@ package.  See the \"Create Frames\"-    section for details.  For even more details, consult the @index-core@-    package.--}--{-# LANGUAGE GADTs, TypeOperators #-}--module Control.Frame (-    -- * Types-    -- $types-    C,-    O,-    M,-    FrameF(..),-    Frame,-    Stack,-    -- * Create Frames-    -- $create--    -- ** Primitives-    -- $primitives-    yieldF,-    awaitF,-    close,-    -- ** Pipe-like primitives-    -- $pipeprims-    yield,-    await,-    -- * Finalize Frames-    -- $finalization-    catchD,-    catchF,-    finallyD,-    finallyF,-    -- * Compose Frames-    -- $compose-    (<-<),-    (>->),-    idF,-    FrameC(..),-    -- * Run Frames-    -- $run-    runFrame-    ) where--import Control.Category-import Control.IMonad-import Control.IMonad.Trans-import Control.IMonad.Trans.Free-import Control.Monad.Instances ()-import Data.Closed (C)-import Data.Maybe-import Prelude hiding ((.), id)---- For documentation-import Control.Pipe hiding (await, yield, Await, Yield)--{- $types-    The first step to convert 'Pipe' code to 'Frame' code is to translate the-    types.  All types of the form \"@Pipe a b m r@\" become-    \"@Frame b m (M a) C r@\".  For example, given the following type signatures-    from the tutorial:--> printer  :: (Show a) => Pipe b C IO r-> take'    :: Int -> Pipe b b IO ()-> fromList :: (Monad m) => [b] -> Pipe () b m ()--    ... you would replace them with:--> printer  :: (Show a) => Frame C IO (M a) C r-> take'    :: Int -> Frame a IO (M a) C ()-> fromList :: (Monad m) => [a] -> Frame a m (M ()) C ()-> -- To use the finalization example, change fromList's base monad to 'IO'-> fromList :: [a] -> Frame a IO (M ()) C ()--}---- | Index representing an open input end, receiving values of type @a@-data O a = O -- Not exported---- | Index representing an open input end, receiving values of type @Maybe a@-type M a = O (Maybe a)--{-|-    Base functor for a pipe that can close its input end--    * @b@ - Output type--    * @x@ - Next step--    * @i@ - Current step's index--}-data FrameF b x i where-    Yield ::  b -> x    i   -> FrameF b x    i-    Await :: (a -> x (O a)) -> FrameF b x (O a)-    Close ::       x    C   -> FrameF b x (O a)--instance IFunctor (FrameF b) where-    fmapI f p = case p of-        Yield b y -> Yield b (f y)-        Await a   -> Await (f . a)-        Close c   -> Close (f c)--{-|-    A 'Frame' is like a 'Pipe' with an indexed input end:--    * @b@ - The type of the 'Frame's output--    * @m@ - The base monad--    * @i@ - The initial index of the input end ('O'pen or 'C'losed)--    * @j@ - The final index of the input end ('O'pen or 'C'losed)--    * @r@ - The return value--}-type Frame b m i j r = IFreeT (FrameF (m (), b)) (U m) (r := j) i---- | A self-contained 'Frame' that is ready to be run-type Stack m r = Frame C m (M ()) C r---- $create--- The second step to convert 'Pipe' code to 'Frame' code is to change your--- module header to:------ > {-# LANGUAGE RebindableSyntax #-}--- >--- > import Control.IMonad.Do--- > import Control.Frame--- > import Prelude hiding (Monad(..))------ "Control.Frame" replaces all 'Pipe' 'await's and 'yield's with their--- corresponding 'Frame' counterparts.  @Control.IMonad.Do@ rebinds @do@--- notation to work with restricted monads, which also requires using the--- @RebindableSyntax@ extension and hiding the 'Monad' class from the @Prelude@.------ You also must use the restricted monad utility functions, which have the--- same name as their ordinary monad counterparts except with an \'@R@\' suffix,--- such as 'foreverR' instead of 'forever'.  Finally, you must use 'liftU'--- instead of 'lift' to invoke operations in the base monad.------ Finally, every terminating 'Frame' must be 'close'd exactly once before being--- passed to composition.------ > printer = foreverR $ do--- >     a <- await--- >     liftU $ print a--- >--- > take' n = do--- >     replicateMR_ n $ do--- >         a <- await--- >         yield a--- >     close--- >     liftU $ putStrLn "You shall not pass!"--- >--- > fromList xs = do--- >     close--- >     mapMR_ yield xs--{- $primitives-    'yieldF' guards against downstream termination by yielding the most-    up-to-date finalization alongside each value, so that downstream can call-    that finalizer if it terminates before requesting another value.--    'awaitF' intercepts upstream termination by returning a 'Nothing' if-    upstream terminates before providing a value.  Further attempts to request-    input from upstream will terminate the current 'Frame' using the-    return value provided from upstream.--    While 'awaitF' is useful for folds, 'yieldF' is less useful for end-users of-    this library and the higher-order 'catchF' / 'finallyF' finalization-    functions are much more user-friendly.--    Composing two 'Frame's requires that each 'Frame' invokes 'close' exactly-    once.  Anything else will not type-check.  Leave out the 'close' statement-    when writing library components and let the person assembling the components-    for composition specify where the 'close' goes.--    The earlier you 'close' the upstream 'Frame', the earlier it is finalized.-    However, once you 'close' it you may no longer 'await'.--}---- | 'Yield' the most current finalizer for this 'Frame' alongside the value-yieldF :: (Monad m) => m () -> b -> Frame b m i i ()-yieldF m x = liftF $ Yield (m, x) (V ())---- | 'Await' a value from upstream, returning 'Nothing' if upstream terminates-awaitF :: (Monad m) => Frame b m (M a) (M a) (Maybe a)-awaitF = liftF $ Await V---- | 'Close' the input end, calling the finalizers of every upstream 'Frame'-close :: (Monad m) => Frame b m (M a) C ()-close = liftF $ Close (V ())--{- $pipeprims-    The following 'Pipe'-like primitives are built on top of the 'Frame'-    primitives.  They behave identically to their 'Pipe' counterparts and can-    be used as drop-in replacements for them.--}---- | 'yield' a value upstream alongside an empty finalizer-yield :: (Monad m) => b -> Frame b m i i ()-yield = yieldF (return ())---- | 'await' a value from upstream and terminate if upstream terminates-await :: (Monad m) => Frame b m (M a) (M a) a-await = awaitF !>= maybe await returnR--{- $finalization-    The third (and optional) step to convert 'Pipe' code to 'Frame' code is to-    register finalizers for your 'Frame'.  These finalizers may be arbitrarily-    nested:--> printer = foreverR $ catchF (putStrLn "printer interrupted") $ do->     a <- await->     liftU $ print a->-> take' n = finallyF (putStrLn "You shall not pass!") $ do->     replicateMR_ n $ do->         a <- catchF (putStrLn "take' interrupted") await->         yield a->     close->-> fromList xs = catchF (putStrLn "fromList interrupted") $ do->     close->     mapMR_ yield xs--    These convenience functions register block-level finalizers to be called if-    another 'Frame' terminates first.  The naming conventions are:--    * \"catch\" functions (i.e. 'catchD' / 'catchF') call the finalizer only if-      another 'Frame' terminates before the block completes, but will not call-      the finalizer if the block terminates normally.--    * \"finally\" functions (i.e. 'finallyD' / 'finallyF') are like \"catch\"-      functions except that they also call the finalizer if the block terminates-      normally.--    * Functions that end in a \'@D@\' suffix (i.e. 'catchD' / 'finallyD') only-      guard against downstream termination.--    * Functions that end in a \'@F@\' suffix (i.e. 'catchF' / 'finallyF') guard-      against termination in both directions.  You usually want these ones.--    Note that finalization blocks that /begin/ after the 'close' statement may-    only use the \'@D@\'-suffixed version as upstream has been closed off.  This-    is a consequence of a deficiency in Haskell's type system that will take-    time to work around.  However an \'@F@\'-suffixed block that begins before a-    'close' statement may continue through it normally.  So, for code blocks-    after a 'close' statement, use 'catchD' \/ 'finallyD', otherwise use-    'catchF' \/ 'finallyF'.  In future releases, the \'@D@\'-suffixed versions-    will be removed and merged into the \'@F@\'-suffixed versions.--}--{-|-    @catchD m p@ calls the finalizer @m@ if a downstream 'Frame' terminates-    before @p@ finishes.--}-catchD :: (Monad m) => m () -> Frame b m i j r -> Frame b m i j r-catchD m p = IFreeT $ U $ do-    x <- unU $ runIFreeT p-    unU $ runIFreeT $ case x of-        Return r                -> returnI r-        Wrap (Close         p') -> wrap $ Close (catchD m p')-        Wrap (Yield (m', b) p') -> wrap $ Yield (m' >> m, b) (catchD m p')-        Wrap (Await         f ) -> wrap $ Await $ fmap (catchD m) f--{-|-    @catchF m p@ calls the finalizer @m@ if any 'Frame' terminates before @p@-    finishes.--}-catchF :: (Monad m) => m () -> Frame b m (M a) j r -> Frame b m (M a) j r-catchF m p = IFreeT $ U $ do-    x <- unU $ runIFreeT p-    unU $ runIFreeT $ case x of-        Return r                -> returnI r-        Wrap (Close         p') -> wrap $ Close $ catchD m p'-        Wrap (Yield (m', b) p') -> wrap $ Yield (m' >> m, b) (catchF m p')-        Wrap (Await         f ) -> wrap $ Await $ \e -> case e of-            Nothing -> liftU m !> catchF m (f e)-            Just _  ->            catchF m (f e)--{-|-    @finallyD m p@ calls the finalizer @m@ if a downstream 'Frame' terminates-    before @p@ finishes or if @p@ completes normally.--}-finallyD :: (Monad m) => m () -> Frame b m i j r -> Frame b m i j r-finallyD m p = IFreeT $ U $ do-    x <- unU $ runIFreeT p-    unU $ runIFreeT $ case x of-        Return r                -> liftU m !> returnI r-        Wrap (Close         p') -> wrap $ Close (finallyD m p')-        Wrap (Yield (m', b) p') -> wrap $ Yield (m' >> m, b) (finallyD m p')-        Wrap (Await         f ) -> wrap $ Await $ fmap (finallyD m) f--{-|-    @finallyF m p@ calls the finalizer @m@ if any 'Frame' terminates before @p@-    finishes or if @p@ completes normally.--}-finallyF :: (Monad m) => m () -> Frame b m (M a) j r -> Frame b m (M a) j r-finallyF m p = IFreeT $ U $ do-    x <- unU $ runIFreeT p-    unU $ runIFreeT $ case x of-        Return r                -> liftU m !> returnI r-        Wrap (Close         p') -> wrap $ Close $ finallyD m p'-        Wrap (Yield (m', b) p') -> wrap $ Yield (m' >> m, b) (finallyF m p')-        Wrap (Await         f ) -> wrap $ Await $ \e -> case e of-            Nothing -> liftU m !> finallyF m (f e)-            Just _  ->            finallyF m (f e)--(<~<) :: (Monad m)- => IFreeT (FrameF c) (U m) (r := C) (O b)- -> IFreeT (FrameF b) (U m) (r := C) (O a)- -> IFreeT (FrameF c) (U m) (r := C) (O a)-p1 <~< p2 = IFreeT $ U $ do-    x1 <- unU $ runIFreeT p1-    unU $ runIFreeT $ case x1 of-        Wrap (Close   p1') -> wrap $ Close p1'-        Wrap (Yield c p1') -> wrap $ Yield c (p1' <~< p2)-        Wrap (Await   f1 ) -> IFreeT $ U $ do-            x2 <- unU $ runIFreeT p2-            let p1' = IFreeT $ returnI x1-            unU $ runIFreeT $ case x2 of-                Wrap (Close p2')   -> wrap $ Close $ p1' <~| p2'-                Wrap (Yield b p2') -> f1 b <~< p2'-                Wrap (Await f2) -> wrap $ Await $ fmap (\p2'-> p1' <~< p2') f2--(<~|) :: (Monad m)- => IFreeT (FrameF c) (U m) (r := C) (O b)- -> IFreeT (FrameF b) (U m) (r := C)  C- -> IFreeT (FrameF c) (U m) (r := C)  C-p1 <~| p2 = IFreeT $ U $ do-    x1 <- unU $ runIFreeT p1-    unU $ runIFreeT $ case x1 of-        Wrap (Close   p1') -> p1'-        Wrap (Yield c p1') -> wrap $ Yield c (p1' <~| p2)-        Wrap (Await   f1 ) -> IFreeT $ U $ do-            x2 <- unU $ runIFreeT p2-            unU $ runIFreeT $ case x2 of-                Return r           -> returnI r-                Wrap (Yield b p2') -> f1 b <~| p2' --heap :: (Monad m)- => m ()- -> IFreeT (FrameF (m (), c)) (U m) (r := C) (M        b )- -> IFreeT (FrameF (m (), c)) (U m) (r := C) (M (m (), b))-heap m p = IFreeT $ U $ do-    x <- unU $ runIFreeT p-    unU $ runIFreeT $ case x of-        Wrap (Close         p') -> wrap $ Close $ liftU m !> p'-        Wrap (Yield (m', c) p') -> wrap $ Yield (m >> m', c) (heap m p')-        Wrap (Await         f ) -> wrap $ Await $ \e -> case e of-            Nothing      -> heap (return ()) (f  Nothing)-            Just (m', b) -> heap m'          (f $ Just b)--stack :: (Monad m)- => Bool- -> IFreeT (FrameF        b ) (U m) (r := C) (M a)- -> IFreeT (FrameF (Maybe b)) (U m) (r := C) (M a)-stack t p = IFreeT $ U $ do-    x <- unU $ runIFreeT p-    unU $ runIFreeT $ case x of-        Wrap (Close   p') -> wrap $ Close $ warn p'-        Wrap (Yield b p') -> wrap $ Yield (Just b) (stack t p')-        Wrap (Await   f ) ->-            let p' = wrap $ Await $ \e -> stack (isNothing e) (f e)-             in case t of-                    False -> p'-                    True  -> wrap $ Yield Nothing p'--warn :: (Monad m)- => IFreeT (FrameF        b ) (U m) (r := C) C- -> IFreeT (FrameF (Maybe b)) (U m) (r := C) C-warn p = IFreeT $ U $ do-    x <- unU $ runIFreeT p-    unU $ runIFreeT $ case x of-        Return r -> wrap $ Yield Nothing (returnI r)-        Wrap (Yield b p') -> wrap $ Yield (Just b) (warn p')--{- $compose-    The fourth step to convert 'Pipe' code to 'Frame' code is to replace ('<+<')-    with ('<-<'):--> printer <-< take' 3 <-< fromList [1..]--    Like 'Pipe's, Frames form a 'Category' where composition pipes the output-    from the upstream 'Frame' to the input of the downstream 'Frame'.-    Additionally, composition guarantees the following behaviors:--    * 'Frame's receive exactly one 'Nothing' if an upstream 'Frame' terminates.--    * Registered finalizers get called exactly once if a downstream 'Frame'-      terminates.--    * Finalizers are always ordered from upstream to downstream.--    The 'Category' laws cannot be broken, so you don't have to be careful when-    using 'Frame's.--    Note that you may only compose 'Frame's that begin open and end closed.--}---- | Corresponds to ('<<<')/('.') from @Control.Category@-(<-<) :: Monad m- => Frame c m (M b) C r -> Frame b m (M a) C r -> Frame c m (M a) C r-p1 <-< p2 = heap (return ()) p1 <~< stack False p2---- | Corresponds to ('>>>') from @Control.Category@-(>->) :: Monad m- => Frame b m (M a) C r -> Frame c m (M b) C r -> Frame c m (M a) C r-(>->) = flip (<-<)--infixr 9 <-<-infixr 9 >->---- | Corresponds to 'id' from @Control.Category@-idF :: (Monad m) => Frame a m (M a) C r-idF = foreverR $ await !>= yield---- | 'Frame's form a 'Category' instance when you rearrange the type variables-newtype FrameC m r a b = FrameC { unFrameC :: Frame b m (M a) C r }--instance (Monad m) => Category (FrameC m r) where-    id = FrameC idF-    (FrameC p1) . (FrameC p2) = FrameC (p1 <-< p2)--{- $run-    The fifth step to convert 'Pipe' code to 'Frame' code is to use 'runFrame'-    instead of 'runPipe':-->>> runFrame $ printer <-< take' 3 <-< fromList [1..]-1-2-3-fromList interrupted-You shall not pass!-printer interrupted->>> runFrame $ printer <-< take' 3 <-< fromList [1]-1-You shall not pass!-take' interrupted-printer interrupted---}--{-|-    Run the 'Frame' monad transformer, converting it back to the base monad.--    'runFrame' is the 'Frame' equivalent to 'runPipe' and requires a-    self-contained 'Stack'.--}-runFrame :: (Monad m) => Stack m r -> m r-runFrame p = do-    x <- unU $ runIFreeT p-    case x of-        Wrap (Close   p') -> runFrame' p'-        Wrap (Yield _ p') -> runFrame  p'-        Wrap (Await   f ) -> runFrame (f $ Just ())--runFrame' :: (Monad m) => Frame C m C C r -> m r-runFrame' p = do-    x <- unU $ runIFreeT p-    case x of-        Return (V r)      -> return r-        Wrap (Yield _ p') -> runFrame'  p'
− Control/Frame/Tutorial.hs
@@ -1,487 +0,0 @@-{-|-    This module provides the tutorial for "Control.Frame".--}--module Control.Frame.Tutorial (-    -- * Restricted Monads-    -- $restrict1--    -- $extension--    -- $restrict2--    -- * Type Signatures-    -- $types--    -- * Prompt Finalization-    -- $prompt--    -- * Composition-    -- $compose--    -- * Finalization-    -- $ensure--    -- * Folds-    -- $fold--    -- * Strictness-    -- $strict--    -- * Robustness-    -- $robust-    ) where---- For documentation-import Control.Category-import Control.Frame-import Control.IMonad-import Control.IMonad.Trans-import Control.Monad.Trans.Class-import Control.Pipe hiding (await, yield, Await, Yield)--{- $restrict1-    'Frame's extend 'Pipe's with two new features:--    * Folding input and intercepting upstream termination--    * Guaranteeing prompt and deterministic finalization--    However, these extra features comes with some added complexity: restricted-    monads, also known as indexed monads.  Restricted monads sound scarier than-    they are, so I'll demonstrate that if you are comfortable using monads, then-    you'll be comfortable using restricted monads.--    Let's translate the @take'@ function from the 'Pipe's tutorial into a-    'Frame' to see what changes when we use restricted monads:---}--- $extension--- > {-# LANGUAGE RebindableSyntax #-}--- >--- > import Control.Frame--- > import Control.IMonad.Do--- > import Control.IMonad.Trans--- > import Prelude hiding (Monad(..))--- >--- > take' :: Int -> Frame a IO (M a) C ()--- > take' n = do--- >     replicateMR_ n $ do--- >         x <- await--- >         yield x--- >     close--- >     liftU $ putStrLn "You shall not pass!"-{- $restrict2-    This time I included all imports and highlighted the new @RebindableSyntax@-    extension.  The new imports belong to the @Control.IMonad@ hierarchy from-    the @index-core@ package, which provides the core restricted monad-    functionality.--    Yet, you almost wouldn't even know you were using an restricted monad just-    by looking at the code.  This is because @index-core@ can rebind @do@-    notation to use restricted monads instead of ordinary extensions.  Three-    things make this possible:--    * The @RebindableSyntax@ extension, which allows libraries to override-      @do@ syntax (among other things)--    * The @Control.IMonad.Do@ module which exports the new bindings for @do@-      notation--    * Hiding 'Monad' from the Prelude so that it does not conflict with the-      bindings from @index-core@--    However, you are not obligated to rebind @do@ notation to use 'Frame's.  You-    can choose to keep ordinary @do@ notation and desugar the restricted monad-    by hand.  Just import @Control.IMonad@ instead, drop the @RebindableSyntax@-    extension, and don't hide 'Monad'.  Then you can desugar @take'@ manually-    using the restricted monad operators:--> import Control.Frame-> import Control.IMonad-> import Control.IMonad.Trans->-> take' :: Int -> Frame a IO (M a) C ()-> take' n =->     (replicateMR_ n $->         await !>= \x -> ->         yield x) !>= \_ ->->     close        !>= \_ ->->     liftU $ putStrLn "You shall not pass!"--    However, for this tutorial I will use the @do@ notation, since it's prettier-    and easier to use.--    You'll also notice functions that resemble the ones in @Control.Monad@,-    except with an \'@R@\' suffix on the end of them, like 'replicateMR_'.-    Most functions in @Control.Monad@ have a restricted counterpart provided by-    @Control.IMonad.Restrict@ (which is in turn re-exported by-    @Control.IMonad@), such as 'whenR', 'foreverR', and 'mapMR'.--    Also, every time you lift an operation from the base monad, you must use-    'liftU' instead of 'lift'.  'Frame's are \"restricted monad transformers\",-    and they would normally lift a base restricted monad using 'liftI', but-    they can also lift ordinary monads, too, using 'liftU' (mnemonic: \"lift\"-    an ordinary monad and \'U\'pgrade it to a restricted monad).--}--{- $types-    The 'Frame' type constructor also looks a bit different, too:--> Frame a IO (M a) C ()--    Let's dissect that to understand how 'Frame's work:-->       | Output | Base monad | Initial Input | Final Input | Return Value-> Frame   a        IO           (M a)           C             ()--    'Frame's differ from 'Pipe's in that their input end indexes the beginning-    and end of the operation.  Our @take'@ function starts off with an open-    input end (@M a@), and ends with a closed input end (@C@).--    @take'@ finishes with a closed input end because it called the 'close'-    function, which seals off and finalizes upstream.  You can see that the-    'close' primitive changes the index just by looking at its type:--> close :: Monad m => Frame b m (M a) C ()--    The 'close' instruction begins with an open input end (@M a@) and finishes-    with a closed input end (@C@).  If you tried to call 'close' twice, you'd-    get a type error:--> -- wrong!-> do close->    close--    This prevents you from accidentally finalizing upstream twice.--    'close' is the only primitive that changes the index, and there is no way to-    reopen the input once you have closed it.  'close' also forbids you from-    'await'ing input from upstream after you have already closed it.  If you-    try, you will get a type error--> -- wrong!-> do close->    await--    This prevents you from requesting input from a finalized pipe.  In fact,-    once you 'close' your input end, every upstream 'Frame' disappears-    completely.  You couldn't get input from upstream anyway, even if you-    somehow allowed 'await' statements after 'close'.--    You can check out 'await''s type signature to see why it won't type-check-    after 'close':--> await :: Monad m => Frame b m (M a) (M a) a--    'await' must begin with the input end open (@M a@) and it leaves the input-    end open when done (@M a@).  However, you can still use a 'yield' anywhere:--> yield :: Monad m => b -> Frame b m i i ()--    'yield' will work whether or not the input end is open, and it leaves the-    input end in the same state once 'yield' is done.--}--{- $prompt-    Every 'Frame' must close its input end /exactly/ one time before you can-    compose it with other 'Frame's.  The only exception is if a 'Frame' never-    terminates:--> -- This type-checks because foreverR is polymorphic in the final index-> printer :: (Show b) => Frame C IO (M b) C r-> printer = foreverR $ do->     a <- await->     liftU $ print a--    However, when a 'Frame' no longer needs input then you should 'close' it as-    early as possible.  The earlier you 'close' upstream, the more promptly-    upstream gets finalized.--    If you write a stand-alone producer from start to finish, you can be sure it-    will never need upstream, so you can close it immediately:--> -- I'm keeping fromList's input end polymorphic for a later example-> fromList :: (M.Monad m) => [b] -> Frame b m (M a) C ()-> fromList xs = do->     close->     mapMR_ yield xs--    However, if @fromList@ were a library function, you would remove the 'close'-    statement as you cannot guarantee that your user won't want to 'await' after-    @fromList@.  Or, the user might want to call @fromList@ twice within the-    same 'Frame', and having two close statements would lead to a type error.-    Therefore, a good rule of thumb when writing library code for 'Frame's is to-    always let the user decide when to 'close' the 'Frame' unless you are-    writing a stand-alone 'Frame'.--    So for right now, I will leave the 'close' in @fromList@ for simplicity and-    treat it as a stand-alone 'Frame'.  Also, it will come in handy for a later-    example.--}--{- $compose-    Composition works just like 'Pipe's, except you use the ('<-<') composition-    operator instead of ('<+<'):--> stack :: Stack IO ()-> stack = printer <-< take' 3 <-< fromList [1..]--    The 'Frame' equivalent to 'Pipeline' is a 'Stack' (mnemonic: call stack;-    also the name 'Frame' refers to a call stack frame):--> type Stack m r = Frame C m (M ()) C r--    Similarly, you use 'runFrame' instead of 'runPipe' to convert the 'Frame'-    back to the base monad:-->>> runFrame stack-1-2-3-You shall not pass!--    However, let's carefully inspect the type of composition:--> (<-<) :: Monad m->  => Frame c m (M b) C r->  -> Frame b m (M a) C r->  -> Frame c m (M a) C r--    Each argument 'Frame' must begin in an open state and end in a closed state.-    This means that each 'Frame' in a 'Stack' must call 'close' exactly once-    before it may be used.  'runFrame' has the exact same restriction:--> runFrame :: Monad m => Stack m r -> m r-> runFrame ~  Monad m => Frame C m (M ()) C r -> m r--    Composition specifically requires the user to define when to finalize-    upstream and does not assume this occurs at the end of the 'Frame'.  This-    doesn't pose a problem for stand-alone 'Frame's, since they will know when-    they no longer need input, but smaller library components designed to be-    assembled into larger 'Frame's should let the user decide at the very last-    moment where to 'close' the 'Pipe'.  There is no way to know ahead of time-    where the 'close' should be until the complete 'Frame' has been assembled.--}--{- $ensure-    With 'Frame's in hand, we can now write a safe @read'@ function:--> readFile' :: Handle -> Frame Text IO C C ()-> readFile' h = do->     eof <- liftU $ hIsEOF h->     whenR (not eof) $ do->         s <- liftU $ hGetLine h->         yield s->         readFile' h-> -> read' :: FilePath -> Frame Text IO C C ()-> read' file = do->     liftU $ putStrLn "Opening file..."->     h <- liftU $ openFile file ReadMode->     -- The following requires "import qualified Control.Monad as M"->     finallyD (putStrLn "Closing file ..." M.>> hClose h) $ readFile' h--    The 'finallyD' function registers a block-level finalizer that executes if a-    downstream 'Pipe' terminates or if the block completes normally.  The more-    general 'finallyF' function will call the finalizer if /any/ 'Frame'-    terminates.--    Usually you would always want to use 'finallyF', but because of some type-    limitations you can only use 'finallyD' after a 'Frame' is closed.  A future-    release of this library will fix this and merge 'finallyD' into 'finallyF'.-    So that means that for everything beginning before a 'close' statement, use-    'finallyF', otherwise use 'finallyD'.--    Similarly, you can use the 'catchF' / 'catchD' counterparts to the-    \"finally\" functions.  The \"catch\" functions run the finalizer only if-    another 'Frame' terminates before the block is done, but not if the block-    terminates normally.--    We don't 'close' the @read'@ function because it's not a stand-alone-    'Frame'.  We want to be able to concatenate multiple @read'@s together-    within the same 'Frame', like so:--> files = do->     close->     read' "file1.txt"->     read' "file2.txt"--    So let's assume those two files have the following contents:--    \"@file1.txt@\"--> Line 1-> Line 2-> Line 3--    \"@file2.txt@\"--> A-> B-> C--    We can now check to see if our @files@ producer works:-->>> runFrame $ printer <-< files-Opening file...-"Line1"-"Line2"-"Line3"-Closing file ...-Opening file...-"A"-"B"-"C"-Closing file ...--    More importantly, files are never opened if they aren't demanded and they-    are always properly finalized if the consumer terminates early:-->>> runFrame $ printer <-< take' 2 <-< files-Opening file...-"Line1"-"Line2"-Closing file ...-You shall not pass!--    So we get lazy, deterministic, and prompt resource management.  Nice!---}--{- $fold-    'Frame's can actually do more than just manage finalization!  Using-    'Frame's, we can now correctly implement folds like @toList@ in a way that-    is truly compositional:--> toList :: (M.Monad m) => Frame b m (M a) (M a) [a]-> toList = do->     a' <- awaitF->     case a' of->         Nothing -> return []->         Just a  -> do->             as <- toList->             return (a:as)--    We used one new function this time: 'awaitF'.  This is like 'await' except-    that it returns a 'Nothing' if upstream terminates before 'yield'ing back a-    value.  This allows you to intercept upstream termination and do some-    cleanup, and in our case we use it to end the fold.--    You only receive a 'Nothing' once when you use 'awaitF'.  Any attempt to-    request more input after you receive the first 'Nothing' will terminate the-    current 'Frame' using the upstream return value.  In fact, 'await' is built-    on top of 'awaitF':--> await = do->     a' <- awaitF->     case a' of->         Nothing -> await->         Just a  -> return a--    If it gets a 'Nothing', it just ignores it and 'await's again, choosing to-    not do any cleanup.--    Now let's make sure our @toList@ function works.  I didn't make @toList@ a-    stand-alone 'Frame', so we will have to include a 'close' statement to-    complete it before composing it:--> p1 = do->     xs <- toList->     close->     return (Just xs)->-> p2 xs = do->     fromList xs->     return Nothing -- Remember: they need the same return type-->>> runFrame $ p1 <-< p2 [1..10]-Just [1,2,3,4,5,6,7,8,9,10]--}--{- $strict-    Lazy resource management has one important disadvantage: we can't free the-    resource until downstream no longer needs input.  Many libraries duplicate-    their code to provide Lazy and Strict versions, allowing the user to decide-    if they want:--    * Lazy input, which conserves memory, but holds onto the resource until-      downstream is done processing it--    * Strict input, which loads everything into memory, but can then immediately-      dispose of the resource before the input is processed--    What if there were a way to seamlessly switch between those semantics or-    even choose something in between?  Well, it turns out we can!--    First, we can combine @fromList@ and @toList@ into something even cooler:--> strict :: (M.Monad m) => Frame a m (M a) C ()-> strict = do->     xs <- toList->     fromList xs--    As the name suggests, the @strict@ function is strict in its input.-    @strict@ loads the entire input into memory, finalizes upstream, then-    proceeds to hand the input off to downstream.  We can prove this just by-    using it:-->>> runFrame $ printer <-< strict <-< files-> Opening file...-> Closing file ...-> Opening file...-> Closing file ...-> "Line1"-> "Line2"-> "Line3"-> "A"-> "B"-> "C"--    Both files were disposed of immediately, at the expense of using more-    memory.--    But what if we want something in between strictness and laziness?  Maybe -    something like this:-->>> runFrame $ printer <-< strict <-< take' 2 <-< files-Opening file...-Closing file ...-You shall not pass!-"Line1"-"Line2"--    Now we have the best of both worlds.  We can pick and choose how much of-    our source to strictly load into memory.  In the above example, we specified-    that we wanted to be strict only in the first two lines of our input, and as-    a result the third line of \"@file1.txt@\" is never read and \"@file2.txt@\"-    is never even opened!--    Now we have a way to seamlessly slide anywhere on the spectrum between-    laziness and strictness, and it's all implemented entirely within Haskell-    in a way that is elegant and intuitive without the use of artificial and-    clumsy 'seq' annotations.--}--{- $robust-    The 'Frame' implementation exposes all internals, yet this does not-    compromise safety or invariants in any way.  The library's implementation is-    \"correct-by-construction\", meaning that you can extend it with your own-    features if you so choose, and you never have to worry about accidentally-    breaking any laws, such as the associativity of composition.--    This has the following important practical benefits for finalization and-    folds:--    * Finalizers never get duplicated or dropped--    * Folds can be performed anywhere within the 'Stack', not just at the most-      downstream 'Frame', as the @strict@ example illustrates.--    * You can reason about each 'Frame's finalization behavior completely-      independently of other 'Frame's.--    Composition elegantly handles every single corner case.  This directly-    follows from strictly enforcing the 'Category' laws, because categories have-    no corners!--}
− Control/IMonad/Trans/Free.hs
@@ -1,56 +0,0 @@--- | This module is the indexed version of "Control.Monad.Trans.Free"--{-# LANGUAGE KindSignatures, TypeOperators #-}--module Control.IMonad.Trans.Free (-    -- * Free monad transformers-    -- $freet-    IFreeF(..),-    IFreeT(..),-    wrap,-    liftF-    ) where--import Control.Category.Index-import Control.IMonad-import Control.IMonad.Trans--{- $freet-    Indexed free monad transformers lift the constructor signatures to-    the category of indexed Haskell functions: (':->').--> Return ::   r :-> IFreeF f r x-> Wrap   :: f x :-> IFreeF f r x->-> IFreeT :: m (IFreeF f r (IFreeT f m r)) :-> IFreeT f m r--}---- | Indexed equivalent to @FreeF@-data IFreeF f r (x :: * -> *) i = Return (r i) | Wrap (f x i)---- | Indexed equivalent to @FreeT@-newtype IFreeT f m r i = IFreeT { runIFreeT :: m (IFreeF f r (IFreeT f m r)) i }--instance (IFunctor f, IMonad m) => IFunctor (IFreeT f m) where-    fmapI f x = x ?>= returnI . f--instance (IFunctor f, IMonad m) => IMonad (IFreeT f m) where-    returnI = IFreeT . returnI . Return-    bindI f m = IFreeT $-        runIFreeT m ?>= \x ->-        runIFreeT $ case x of-            Return r -> f r-            Wrap   w -> wrap $ fmapI (bindI f) w--instance (IFunctor f) => IMonadTrans (IFreeT f) where-    liftI = IFreeT . fmapI Return---- | Indexed equivalent to @wrap@-wrap :: (IMonad m) => f (IFreeT f m r) :-> IFreeT f m r-wrap = IFreeT . returnI . Wrap---- | Indexed equivalent to @liftF@-liftF :: (IFunctor f, IMonad m) => f r :-> IFreeT f m r-liftF x = wrap $ fmapI returnI x---- FIXME: Add IIdentity so that IFree can be defined in terms of IFreeT
Control/MFunctor.hs view
@@ -3,12 +3,54 @@ {-# LANGUAGE Rank2Types #-}  module Control.MFunctor (-    -- * Monads over functors-    MFunctor(..)+    -- * Functors over Monads+    MFunctor(..),+    raise     ) where +import Control.Monad.Trans.Class (MonadTrans(lift))+import Control.Monad.Trans.Identity (IdentityT, mapIdentityT)+import Control.Monad.Trans.Maybe (MaybeT, mapMaybeT)+import Control.Monad.Trans.Reader (ReaderT, mapReaderT)+import Control.Monad.Trans.RWS (RWST, mapRWST)+import qualified Control.Monad.Trans.State.Strict as StateStrict+import qualified Control.Monad.Trans.State.Lazy   as StateLazy +import qualified Control.Monad.Trans.Writer.Strict as WriterStrict+import qualified Control.Monad.Trans.Writer.Lazy   as WriterLazy+ -- | A functor in the category of monads class MFunctor t where     {-| Lift a monad morphism from @m@ to @n@ into a monad morphism from         @(t m)@ to @(t n)@ -}-    mapT :: (Monad m, Monad n) => (forall a . m a -> n a) -> t m b -> t n b+    hoist :: (Monad m) => (forall a . m a -> n a) -> t m b -> t n b++instance MFunctor IdentityT where+    hoist nat = mapIdentityT nat++instance MFunctor MaybeT where+    hoist nat = mapMaybeT nat++instance MFunctor (ReaderT r) where+    hoist nat = mapReaderT nat++instance MFunctor (RWST r w s) where+    hoist nat = mapRWST nat++instance MFunctor (StateStrict.StateT s) where+    hoist nat = StateStrict.mapStateT nat++instance MFunctor (StateLazy.StateT s) where+    hoist nat = StateLazy.mapStateT nat++instance MFunctor (WriterStrict.WriterT w) where+    hoist nat = WriterStrict.mapWriterT nat++instance MFunctor (WriterLazy.WriterT w) where+    hoist nat = WriterLazy.mapWriterT nat++{-| Lift the base monad++> raise = hoist lift+-}+raise :: (Monad m, MFunctor t1, MonadTrans t2) => t1 m r -> t1 (t2 m) r+raise = hoist lift
+ Control/PFunctor.hs view
@@ -0,0 +1,32 @@+-- | This module defines functors in the category of proxies++{-# LANGUAGE KindSignatures, Rank2Types #-}++module Control.PFunctor (+    -- * Functors over Proxies+    PFunctor(..),+    raiseP+    ) where++import Control.Proxy.Class (Proxy)+import Control.Proxy.Trans (ProxyTrans(liftP))++-- | A functor in the category of monads+class PFunctor (+    t :: (* -> * -> * -> * -> (* -> *) -> * -> *)+      ->  * -> * -> * -> * -> (* -> *) -> * -> * ) where+    {-| Lift a proxy morphism from @p@ to @q@ into a proxy morphism from+        @(t p)@ to @(t q)@ -}+    hoistP+     :: (Monad m, Proxy p)+     => (forall a' a b' b r1 . p a' a b' b m r1 -> q a' a b' b m r1)+     -> (t p a' a b' b m r2 -> t q a' a b' b m r2)++{-| Lift the base proxy++> raiseP = hoistP liftP+-}+raiseP+ :: (Monad m, Proxy p, PFunctor t1, ProxyTrans t2)+ => t1 p a' a b' b m r -> t1 (t2 p) a' a b' b m r+raiseP = hoistP liftP
Control/Pipe.hs view
@@ -1,14 +1,200 @@--- | Top-level import for the "Control.Pipe" hierarchy+{-| This module remains as a wistful reminder of this library's humble origins.+    This library now builds upon the more general 'Proxy' type, but still keeps+    the @pipes@ name.  Read "Control.Proxy.Tutorial" to learn about this new+    implementation. +    The 'Pipe' type is a monad transformer that enriches the base monad with the+    ability to 'await' or 'yield' data to and from other 'Pipe's. -}+ module Control.Pipe (-    -- * Modules-    -- $modules-    module Control.Pipe.Core+    -- * Types+    -- $types+    Pipe(..),+    Producer,+    Consumer,+    Pipeline,+    -- * Create Pipes+    -- $create+    await,+    yield,+    pipe,+    -- * Compose Pipes+    -- $category+    (<+<),+    (>+>),+    idP,+    PipeC(..),+    -- * Run Pipes+    runPipe     ) where -import Control.Pipe.Core+import Control.Applicative (Applicative(pure, (<*>)))+import Control.Category (Category((.), id), (<<<), (>>>))+import Control.Monad (forever)+import Control.Monad.Trans.Class (MonadTrans(lift))+import Control.Proxy.Synonym (C)+import Prelude hiding ((.), id) -{- $modules-    "Control.Pipe.Core" provides the core type and primitives.-  -    "Control.Pipe.Tutorial" provides an extended tutorial. -}+{- $types+    The 'Pipe' type is strongly inspired by Mario Blazevic's @Coroutine@ type in+    his concurrency article from Issue 19 of The Monad Reader.+-}++{-|+    The base type for pipes++    * @a@ - The type of input received from upstream pipes++    * @b@ - The type of output delivered to downstream pipes++    * @m@ - The base monad++    * @r@ - The type of the return value+-}+data Pipe a b m r+  = Await (a -> Pipe a b m r)+  | Yield b    (Pipe a b m r)+  | M       (m (Pipe a b m r))+  | Pure r+{-+Technically, the correct implementation that satisfies the monad transformer+laws is:++type PipeF a b x = Await (a -> x) | Yield b x deriving (Functor)++type Pipe a b = FreeT (PipeF a b)+-}++instance (Monad m) => Functor (Pipe a b m) where+    fmap f pr = go pr where+        go p = case p of+            Await   k  -> Await (\a -> go (k a))+            Yield b p' -> Yield b (go p')+            M       m  -> M (m >>= \p' -> return (go p'))+            Pure    r  -> Pure (f r)++instance (Monad m) => Applicative (Pipe a b m) where+    pure = Pure+    pf <*> px = go pf where+        go p = case p of+            Await   k  -> Await (\a -> go (k a))+            Yield b p' -> Yield b (go p')+            M       m  -> M (m >>= \p' -> return (go p'))+            Pure    f  -> fmap f px++instance (Monad m) => Monad (Pipe a b m) where+    return  = Pure+    pm >>= f = go pm where+        go p = case p of+            Await   k  -> Await (\a -> go (k a))+            Yield b p' -> Yield b (go p')+            M       m  -> M (m >>= \p' -> return (go p'))+            Pure    r  -> f r++instance MonadTrans (Pipe a b) where+    lift m = M (m >>= \r -> return (Pure r))++-- | A pipe that produces values+type Producer b m r = Pipe () b m r++-- | A pipe that consumes values+type Consumer a m r = Pipe a C m r++-- | A self-contained pipeline that is ready to be run+type Pipeline m r = Pipe () C m r++{- $create+    'yield' and 'await' are the only two primitives you need to create pipes.+    Since @Pipe a b m@ is a monad, you can assemble 'yield' and 'await'+    statements using ordinary @do@ notation.  Since @Pipe a b@ is also a monad+    transformer, you can use 'lift' to invoke the base monad.  For example, you+    could write a pipe stage that requests permission before forwarding any+    output:++> check :: (Show a) => Pipe a a IO r+> check = forever $ do+>     x <- await+>     lift $ putStrLn $ "Can '" ++ (show x) ++ "' pass?"+>     ok <- read <$> lift getLine+>     when ok (yield x)+-}++{-|+    Wait for input from upstream.++    'await' blocks until input is available from upstream.+-}+await :: Pipe a b m a+await = Await Pure++{-|+    Deliver output downstream.++    'yield' restores control back upstream and binds its value to 'await'.+-}+yield :: b -> Pipe a b m ()+yield b = Yield b (Pure ())++{-|+    Convert a pure function into a pipe++> pipe f = forever $ do+>     x <- await+>     yield (f x)+-}+pipe :: (Monad m) => (a -> b) -> Pipe a b m r+pipe f = go where+    go = Await (\a -> Yield (f a) go)++{- $category+    'Pipe's form a 'Category', meaning that you can compose 'Pipe's using+    ('>+>') and also define an identity 'Pipe': 'idP'.  These satisfy the+    category laws:++> idP >+> p = p+>+> p >+> idP = p+>+> (p1 >+> p2) >+> p3 = p1 >+> (p2 >+> p3)++    @(p1 >+> p2)@ satisfies all 'await's in @p2@ with 'yield's in @p1@.  If any+    'Pipe' terminates the entire 'Pipeline' terminates.+-}++-- | 'Pipe's form a 'Category' instance when you rearrange the type variables+newtype PipeC m r a b = PipeC { unPipeC :: Pipe a b m r}++instance (Monad m) => Category (PipeC m r) where+    id = PipeC idP+    PipeC p1 . PipeC p2 = PipeC $ p1 <+< p2++-- | Corresponds to ('<<<')/('.') from @Control.Category@+(<+<) :: (Monad m) => Pipe b c m r -> Pipe a b m r -> Pipe a c m r+(Yield b p1) <+< p2 = Yield b (p1 <+< p2)+(M       m ) <+< p2 = M (m >>= \p1 -> return (p1 <+< p2))+(Pure    r ) <+< _  = Pure r+(Await   k ) <+< (Yield b p2) = k b <+< p2+p1 <+< (Await k) = Await (\a -> p1 <+< k a)+p1 <+< (M     m) = M (m >>= \p2 -> return (p1 <+< p2))+_  <+< (Pure  r) = Pure r++-- | Corresponds to ('>>>') from @Control.Category@+(>+>) :: (Monad m) => Pipe a b m r -> Pipe b c m r -> Pipe a c m r+p2 >+> p1 = p1 <+< p2++infixr 8 <+<+infixl 8 >+>++-- | Corresponds to 'id' from @Control.Category@+idP :: (Monad m) => Pipe a a m r+idP = go where+    go = Await (\a -> Yield a go)++-- | Run the 'Pipe' monad transformer, converting it back into the base monad+runPipe :: (Monad m) => Pipe () b m r -> m r+runPipe pl = go pl where+    go p = case p of+       Yield _ p' -> go p' +       Await   k  -> go (k ())+       M       m  -> m >>= go+       Pure    r  -> return r
− Control/Pipe/Core.hs
@@ -1,230 +0,0 @@-{-| The 'Pipe' type is a monad transformer that enriches the base monad with the-    ability to 'await' or 'yield' data to and from other 'Pipe's. -}--module Control.Pipe.Core (-    -- * Types-    -- $types-    Pipe(..),-    C,-    Producer,-    Consumer,-    Pipeline,-    -- * Create Pipes-    -- $create-    await,-    yield,-    pipe,-    -- * Compose Pipes-    -- $category-    (<+<),-    (>+>),-    idP,-    PipeC(..),-    -- * Run Pipes-    -- $runpipe-    runPipe-    ) where--import Control.Applicative (Applicative(pure, (<*>)))-import Control.Category (Category((.), id), (<<<), (>>>))-import Control.Monad (forever)-import Control.Monad.Trans.Class (MonadTrans(lift))-import Data.Closed (C)-import Prelude hiding ((.), id)--{- $types-    The 'Pipe' type is strongly inspired by Mario Blazevic's @Coroutine@ type in-    his concurrency article from Issue 19 of The Monad Reader.--}--{-|-    The base type for pipes--    * @a@ - The type of input received from upstream pipes--    * @b@ - The type of output delivered to downstream pipes--    * @m@ - The base monad--    * @r@ - The type of the return value--}-data Pipe a b m r-  = Await (a -> Pipe a b m r)-  | Yield b    (Pipe a b m r)-  | M       (m (Pipe a b m r))-  | Pure r-{--type PipeF a b x = Await (a -> x) | Yield b x deriving (Functor)--type Pipe a b = FreeT (PipeF a b)--}--instance (Monad m) => Functor (Pipe a b m) where-    fmap f pr = go pr where-        go p = case p of-            Await   k  -> Await (\a -> go (k a))-            Yield b p' -> Yield b (go p')-            M       m  -> M (m >>= \p' -> return (go p'))-            Pure    r  -> Pure (f r)--instance (Monad m) => Applicative (Pipe a b m) where-    pure = Pure-    pf <*> px = go pf where-        go p = case p of-            Await   k  -> Await (\a -> go (k a))-            Yield b p' -> Yield b (go p')-            M       m  -> M (m >>= \p' -> return (go p'))-            Pure    f  -> fmap f px--instance (Monad m) => Monad (Pipe a b m) where-    return  = Pure-    pm >>= f = go pm where-        go p = case p of-            Await   k  -> Await (\a -> go (k a))-            Yield b p' -> Yield b (go p')-            M       m  -> M (m >>= \p' -> return (go p'))-            Pure    r  -> f r--instance MonadTrans (Pipe a b) where-    lift m = M (m >>= \r -> return (Pure r))---- | A pipe that produces values-type Producer b = Pipe () b---- | A pipe that consumes values-type Consumer b = Pipe b C---- | A self-contained pipeline that is ready to be run-type Pipeline = Pipe () C--{- $create-    'yield' and 'await' are the only two primitives you need to create pipes.-    Since @Pipe a b m@ is a monad, you can assemble 'yield' and 'await'-    statements using ordinary @do@ notation.  Since @Pipe a b@ is also a monad-    transformer, you can use 'lift' to invoke the base monad.  For example, you-    could write a pipe stage that requests permission before forwarding any-    output:--> check :: (Show a) => Pipe a a IO r-> check = forever $ do->     x <- await->     lift $ putStrLn $ "Can '" ++ (show x) ++ "' pass?"->     ok <- read <$> lift getLine->     when ok (yield x)--}--{-|-    Wait for input from upstream.--    'await' blocks until input is available from upstream.--}-await :: Pipe a b m a-await = Await Pure--{-|-    Deliver output downstream.--    'yield' restores control back upstream and binds the result to 'await'.--}-yield :: b -> Pipe a b m ()-yield b = Yield b (Pure ())--{-|-    Convert a pure function into a pipe--> pipe f = forever $ do->     x <- await->     yield (f x)--}-pipe :: (Monad m) => (a -> b) -> Pipe a b m r-pipe f = go where-    go = Await (\a -> Yield (f a) go)--{- $category-    'Pipe's form a 'Category', meaning that you can compose 'Pipe's using-    ('<+<') and also define an identity 'Pipe': 'idP'.  These satisfy the-    category laws:--> idP <+< p = p->-> p <+< idP = p->-> (p1 <+< p2) <+< p3 = p1 <+< (p2 <+< p3)--    'Pipe' composition binds the output of the upstream 'Pipe' to the input of-    the downstream 'Pipe'.  Like Haskell functions, 'Pipe's are lazy, meaning-    that upstream 'Pipe's are only evaluated as far as necessary to generate-    enough input for downstream 'Pipe's.  If any 'Pipe' terminates, it also-    terminates every 'Pipe' composed with it.--}---- | 'Pipe's form a 'Category' instance when you rearrange the type variables-newtype PipeC m r a b = PipeC { unPipeC :: Pipe a b m r}--instance (Monad m) => Category (PipeC m r) where-    id = PipeC idP-    PipeC p1 . PipeC p2 = PipeC $ p1 <+< p2---- | Corresponds to ('<<<')/('.') from @Control.Category@-(<+<) :: (Monad m) => Pipe b c m r -> Pipe a b m r -> Pipe a c m r-(Yield b p1) <+< p2 = Yield b (p1 <+< p2)-(M       m ) <+< p2 = M (m >>= \p1 -> return (p1 <+< p2))-(Pure    r ) <+< _  = Pure r-(Await   k ) <+< (Yield b p2) = k b <+< p2-p1 <+< (Await k) = Await (\a -> p1 <+< k a)-p1 <+< (M     m) = M (m >>= \p2 -> return (p1 <+< p2))-_  <+< (Pure  r) = Pure r---- | Corresponds to ('>>>') from @Control.Category@-(>+>) :: (Monad m) => Pipe a b m r -> Pipe b c m r -> Pipe a c m r-p2 >+> p1 = p1 <+< p2--{- These associativities might help performance since pipe evaluation is-   downstream-biased.  I set them to the same priority as (.). -}-infixr 9 <+<-infixl 9 >+>---- | Corresponds to 'id' from @Control.Category@-idP :: (Monad m) => Pipe a a m r-idP = go where-    go = Await (\a -> Yield a go)--{- $runpipe-    Note that you can also unwrap a 'Pipe' a single step at a time using-    'runFreeT' (since 'Pipe' is just a type synonym for a free monad-    transformer).  This will take you to the next /external/ 'await' or 'yield'-    statement.  This means that a closed 'Pipeline' will unwrap to a single-    step, in which case you would have been better served by 'runPipe'.--}-{-|-    Run the 'Pipe' monad transformer, converting it back into the base monad.--    'runPipe' imposes two conditions:--    * The pipe's input, if any, is trivially satisfiable (i.e. @()@)--    * The pipe does not 'yield' any output--    The latter restriction makes 'runPipe' less polymorphic than it could be,-    and I settled on the restriction for three reasons:--    * It prevents against accidental data loss.--    * It protects against silent failures--    * It prevents wastefully draining a scarce resource by gratuitously-      driving it to completion--    If you believe that discarding output is the appropriate behavior, you can-    specify this by explicitly feeding your output to a pipe that gratuitously-    discards it:--> runPipe $ forever await <+< p--}-runPipe :: (Monad m) => Pipeline m r -> m r-runPipe pl = go pl where-    go p = case p of-       Yield _ p' -> go p' -       Await   k  -> go (k ())-       M       m  -> m >>= go-       Pure    r  -> return r
− Control/Pipe/Tutorial.hs
@@ -1,539 +0,0 @@-{-|-    This module provides the tutorial for "Control.Pipe".--}--module Control.Pipe.Tutorial (-    -- * Types-    -- $type--    -- * Composition-    -- $compose--    -- * Modularity-    -- $modular--    -- * Vertical Concatenation-    -- $vertical--    -- * Return Values-    -- $return--    -- * Termination-    -- $terminate--    -- * Folds-    -- $folds--    -- * Resource Management-    -- $resource--    -- * Bidirectional Pipes-    -- $bidirectional-    ) where---- For documentation-import Control.Category-import Control.Frame hiding (await, yield)-import Control.Monad.Trans.Class-import Control.Pipe--{- $type-    This library represents unidirectional streaming computations using  the-    'Pipe' type.--    'Pipe' is a monad transformer that extends the base monad with the ability-    to 'await' input from or 'yield' output to other 'Pipe's.  'Pipe's resemble-    enumeratees in other libraries because they receive an input stream and-    transform it into a new output stream.--    I'll introduce our first 'Pipe', which is a verbose version of the Prelude's-    'take' function:--> take' :: Int -> Pipe a a IO ()-> take' n = do->     replicateM_ n $ do->         x <- await->         yield x->     lift $ putStrLn "You shall not pass!"--    This 'Pipe' forwards the first @n@ values it receives undisturbed, then it-    outputs a cute message.--    Let's dissect the above 'Pipe''s type to learn a bit about how 'Pipe's work:-->      | Input Type | Output Type | Base monad | Return value-> Pipe   a            a             IO           ()--    So @take'@ 'await's input values of type \'@a@\' from upstream 'Pipe's and-    'yield's output values of type \'@a@\' to downstream 'Pipe's.  @take'@ uses-    'IO' as its base monad because it invokes the 'putStrLn' function.  If we-    were to remove the call to 'putStrLn', the compiler would infer the-    following type instead, which is polymorphic in the base monad:--> take' :: (Monad m) => Int -> Pipe a a m ()--    Now let's create a function that converts a list into a 'Pipe' by 'yield'ing-    each element of the list:--> fromList :: (Monad m) => [b] -> Pipe a b m ()-> fromList = mapM_ yield--    Note that @fromList xs@ is polymorphic in its input.  This is because it-    does not 'await' any input.  If we wanted, we could type-restrict it to:--> fromList :: (Monad m) => [b] -> Pipe () b m ()--    There is no type that forbids a 'Pipe' from 'await'ing, but you can-    guarantee that if it does 'await', the request is trivially satisfiable by-    supplying it with @()@.--    A 'Pipe' that doesn't 'await' (any useful input) can serve as the first-    stage in a 'Pipeline'.  I provide a type synonym for this common case:--> type Producer b m r = Pipe () b m r--    'Producer's resemble enumerators in other libraries because they function as-    data sources.--    You can then use the 'Producer' type synonym to rewrite the type signature-    for @fromList@ as:--> fromList :: (Monad m) => [b] -> Producer b m ()--    Now let's create a 'Pipe' that prints every value delivered to it:--> printer :: (Show b) => Pipe b c IO r-> printer = forever $ do->     x <- await->     lift $ print x--    Here, @printer@ is polymorphic in its output.  We could type-restrict it to-    guarantee it will never 'yield' by setting the output to 'C', an unhabited-    type that \'@C@\'loses the output end:--> printer :: (Show b) => Pipe b C IO r--    A 'Pipe' that never 'yield's can be the final stage in a 'Pipeline'.  Again,-    I provide a type synonym for this common case:--> type Consumer b m r = Pipe b C m r--    So we could instead write @printer@'s type as:--> printer :: (Show b) => Consumer b IO r--    'Consumer's resemble iteratees in other libraries because they function as-    data sinks.--}--{- $compose-    What distinguishes 'Pipe's from every other iteratee implementation is that-    they form a true 'Category'.  Because of this, you can literally compose-    'Pipe's into 'Pipeline's using ordinary composition:--> newtype PipeC m r a b = PipeC { unPipeC :: Pipe a b m r }-> instance Category (PipeC m r) where ...--    For example, you can compose the above 'Pipe's with:--> pipeline :: Pipe () C IO ()-> pipeline = unPipeC $ PipeC printer . PipeC (take' 3) . PipeC (fromList [1..])--    The compiler deduces that the final 'Pipe' must be blocked at both ends,-    meaning it will never 'await' useful input and it will never 'yield' any-    output.  This represents a self-contained 'Pipeline' and I provide a type-    synonym for this common case:--> type Pipeline m r = Pipe () C m r--    Also, I provide '<+<' as a convenience operator for composing 'Pipe's-    without the burden of wrapping and unwrapping newtypes:--> p1 <+< p2 == unPipeC $ PipeC p1 . PipeC p2--    So you can rewrite @pipeline@ as:--> pipeline :: Pipeline IO ()-> pipeline = printer <+< take' 3 <+< fromList [1..]--    Like many other monad transformers, you convert the 'Pipe' monad back to the-    base monad using some sort of \"@run...@\" function.  In this case, it's the-    'runPipe' function:--> runPipe :: (Monad m) => Pipeline m r -> m r--    'runPipe' only works on self-contained 'Pipeline's, but you don't need to-    worry about explicitly type-restricting any of your 'Pipe's.  Self-contained-    'Pipeline's will automatically have polymorphic input and output ends and-    they will type-check when you provide them to 'runPipe'.--    Let's try using 'runPipe':-->>> runPipe pipeline-1-2-3-You shall not pass!--    Fascinating!  Our 'Pipe' terminates even though @printer@ never terminates-    and @fromList@ never terminates when given an infinite list.  To illustrate-    why our 'Pipe' terminates, let's outline the 'Pipe' flow control rules for-    composition:--    * 'Pipe's are lazy, so execution begins at the most downstream 'Pipe'-      (@printer@ in our example).--    * When a 'Pipe' 'await's, it blocks until it receives input from the next-      'Pipe' upstream--    * When a 'Pipe' 'yield's, it blocks until it receives a new 'await' request-      from downstream.--    * If a 'Pipe' terminates, it terminates every other 'Pipe' composed with it.--    All of these flow control rules uniquely follow from the 'Category' laws.--    It might surprise you that termination brings down the entire 'Pipeline'-    until you realize that:--    * Downstream 'Pipe's depending on the result from the terminated 'Pipe'-      cannot proceed--    * Upstream 'Pipe's won't be further evaluated because the terminated 'Pipe'-      will not request any further input from them--    So in our previous example, the 'Pipeline' terminated because \"@take' 3@\"-    terminated and brought down the entire 'Pipeline' with it.--    Actually, these flow control rules will mislead you into thinking that-    composed 'Pipe's behave as a collection of sub-'Pipe's with some sort of-    message passing architecture between them, but nothing could be further from-    the truth! When you compose 'Pipe's, they automatically fuse into a single-    'Pipe' that corresponds to how you would have written the control flow by-    hand.--    For example, if you compose @printer@ and @fromList@:--> printer <+< fromList [1..]--    The result is indistinguishable from:--> lift (mapM_ print [1..])--    ... which is what we would have written by hand if we had not used 'Pipe's-    at all!  All 'runPipe' does is just remove the 'lift'!--}--{- $modular-    Given a loop like:--> loop :: IO r-> loop = forever $ do->     x <- dataSource->     y <- processData x->     dataSink y--    We could decompose it into three separate parts:--> stage1 :: Producer a IO r-> stage1 = forever $ do->     x <- dataSource->     yield x->-> stage2 :: Pipe a b IO r-> stage2 = forever $ do->     x <- await->     y <- processData x->     yield y->->-> stage3 :: Consumer b IO r-> stage3 = forever $ do->     y <- await->     dataSink y->-> stage3 <+< stage2 <+< stage1 = lift loop--    In other words, 'Pipe's let you decompose loops into modular components,-    which promotes loose coupling and allows you to freely mix and match those-    components.--    To demonstrate this, let's define a new data source that indefinitely-    prompts the user for integers:--> prompt :: Producer Int IO a-> prompt = forever $ do->     lift $ putStrLn "Enter a number: "->     n <- read <$> lift getLine->     yield n--    Now we can use it as a drop-in replacement for @fromList@:-->>> runPipe $ printer <+< take' 3 <+< prompt-Enter a number:-1<Enter>-1-Enter a number:-2<Enter>-2-Enter a number:-3<Enter>-3-You shall not pass!---}--{- $vertical-    You can easily \"vertically\" concatenate 'Pipe's, 'Producer's, and-    'Consumer's, all using simple monad sequencing: ('>>').  For example, here-    is how you concatenate 'Producer's:-->>> runPipe $ printer <+< (fromList [1..3] >> fromList [10..12])-1-2-3-10-11-12--    Here's how you would concatenate 'Consumer's:-->>> let print' n = printer <+< take' n :: (Show a) => Int -> Consumer a IO ()->>> runPipe $ (print' 3 >> print' 4) <+< fromList [1..]-1-2-3-You shall not pass!-4-5-6-7-You shall not pass!--   ... but the above example is gratuitous because we could have just-   concatenated the intermediate @take'@ 'Pipe':-->>> runPipe $ printer <+< (take' 3 >> take' 4) <+< fromList [1..]-1-2-3-You shall not pass!-4-5-6-7-You shall not pass!---}--{- $return-    'Pipe' composition imposes an important requirement: You can only compose-    'Pipe's that have the same return type.  For example, I could write the-    following function:--> deliver :: (Monad m) => Int -> Consumer a m [a]-> deliver n = replicateM n await--    ... and I might try to compose it with @fromList@:-->>> runPipe $ deliver 3 <+< fromList [1..10] -- wrong!--    ... but this wouldn't type-check, because @fromList@ has a return type of-    @()@ and @deliver@ has a return type of @[Int]@.  Composition requires that-    every 'Pipe' has a return value ready in case it terminates first.--    Fortunately, we don't have to rewrite the @fromList@ function because we can-    just add a return value using vertical concatenation:-->>> runPipe $ deliver 3 <+< (fromList [1..10] >> return [])-[1,2,3]--    ... although a more idiomatic Haskell version would be:-->>> runPipe $ (Just <$> deliver 3) <+< (fromList [1..10] *> pure Nothing)-Just [1,2,3]--    This forces you to cover all code paths by thinking about what return value-    you would provide if something were to go wrong.  For example, let's say I-    were to make a mistake and request more input than @fromList@ can deliver:-->>> runPipe $ (Just <$> deliver 99) <+< (fromList [1..10] *> pure Nothing)-Nothing--    The type system saved me by forcing me to cover all corner cases and handle-    every way my program could terminate.--}--{- $terminate--    Now what if you wanted to write a 'Pipe' that only reads from its input end-    (i.e. a 'Consumer') and returns a list of every value delivered to it when-    its input 'Pipe' terminates?--> toList :: (Monad m) => Consumer a m [a]-> toList = ???--    You can't write such a 'Pipe' because if its input terminates then it brings-    down @toList@ with it!  This is correct because @toList@ as defined is not-    compositional (yet!).--    To see why, let's say you somehow got @toList@ to work and the following-    imaginary code sample worked:-->>> runPipe $ toList <+< (fromList [1..5] >> return [])-[1,2,3,4,5]--    @toList@ is defined to return its value when the 'Pipe' immediately upstream-    (@fromList@ in this case) terminates.  This behavior immediately leads to a-    problem.  What if I were to insert an \"identity\" 'Pipe' between @toList@-    and @fromList@:--> identity = forever $ await >>= yield-> -- This is how id is actually implemented!--    This 'Pipe' forwards every valued untouched, so we would expect it to not-    have any affect if we were to insert it in the middle:-->>> runPipe $ toList <+< identity <+< (fromList [1..5] >> return [])-??? -- Oops! Something other than [1,2,3,4,5], perhaps even non-termination--    The answer couldn't be @[1,2,3,4,5]@ because @toList@ would monitor -    @identity@ instead of @fromList@ and since @identity@ never terminates-    @toList@ never terminates.  This is what I mean when I say that @toList@'s-    specified behavior is non-compositional.  It only works if it is coupled-    directly to the desired 'Pipe' and breaks when you introduce intermediate-    stages.--    Note that a terminated 'Pipe' only brings down 'Pipe's composed with it.  To-    illustrate this, let's use the following example:--> p = do a <+< b->        c--    @a@, @b@, and @c@ are 'Pipe's, and @c@ shares the same input and output as-    the composite 'Pipe' @a <+< b@, otherwise we cannot combine them within the-    same monad.  In the above example, either @a@ or @b@ could terminate and-    bring down the other one since they are composed, but @c@ is guaranteed to-    continue after @a <+< b@ terminates because it is not composed with them.-    Conceptually, we can think of this as @c@ automatically taking over the-    'Pipe''s channeling responsibilities when @a <+< b@ can no longer continue.-    There is no need to \"restart\" the input or output manually as in some-    other iteratee libraries.--    The @pipes@ library, unlike other iteratee libraries, grounds its vertical-    and horizontal concatenation in category theory by deriving horizontal-    concatenation ('.') from its 'Category' instance and vertical concatenation-    ('>>') from its 'Monad' instance.  This makes it easier to reason about-    'Pipe's because you can leverage your intuition about 'Category's and-    'Monad's to understand their behavior.  The only 'Pipe'-specific primitives-    are 'await' and 'yield'.--}--{- $folds-    While we cannot intercept termination, we can still fold our input.  We can-    embed 'WriterT' in our base monad, since 'Pipe' is a monad transformer, and-    store the result in the monoid:--> toList :: Consumer a (WriterT [a] m) r-> toList = forever $ do->     a <- await->     lift $ tell [a]-->>> execWriterT $ runPipe $ toList <+< fromList [1..4]-[1,2,3,4]--    But what if other pipes have a base monad that is not compatible, such as:--> prompt3 :: Producer Int IO a-> prompt3 = take' 3 <+< prompt--    That's okay, because we can transparently 'lift' any Pipe's base monad,-    using 'hoistFreeT' from @Control.Monad.Trans.Free@ in the @free@ package:-->>> execWriterT $ runPipe $ toList <+< hoistFreeT lift prompt3-3<Enter>-4<Enter>-6<Enter>-[3,4,6]---}--{- $resource-    Pipes handle streaming computations well, but do not handle resource-    management well.  To see why, let's say we have the file \"@test.txt@\"-    with the following contents:--> Line 1-> Line 2-> Line 3--  .. and we wish to lazily read one line at a time from it:--> readFile' :: Handle -> Producer Text IO ()-> readFile' h = do->     eof <- lift $ hIsEOF h->     when (not eof) $ do->         s <- lift $ hGetLine h->         yield s->         readFile' h--    We could then try to be slick and write a lazy version that only reads as-    many lines as we request:--> read' :: FilePath -> Producer Text IO ()-> read' file = do->     lift $ putStrLn "Opening file ..."->     h <- lift $ openFile file ReadMode->     readFile' h->     lift $ putStrLn "Closing file ..."->     lift $ hClose h--    Now compose!-->>> runPipe $ printer <+< read' "test.xt"-Opening file ...-"Line 1"-"Line 2"-"Line 3"-Closing file ...--    So far, so good.  Equally important, the file is never opened if we replace-    @printer@ with a 'Pipe' that never demands input:-->>> runPipe $ (lift $ putStrLn "I don't need input") <+< read' "test.txt"-I don't need input--    There is still one problem, though. What if we wrote:-->>> runPipe $ printer <+< take' 2 <+< read' "test.txt"-Opening file ...-"Line 1"-"Line 2"-You shall not pass!--    Oh no!  While it was lazy and only read two lines from the file, it was also-    too lazy to properly close our file!  \"@take' 2@\" terminated before-    @read'@, preventing @read'@ from properly closing \"test.txt\".  This is why-    'Pipe' composition fails to guarantee deterministic finalization.--    The "Control.Frame" module of this library provides a temporary solution to-    this problem, but in the longer run there will be a more elegant solution-    built on top of "Control.Proxy".--}--{- $bidirectional-    The 'Pipe' type suffers from one restriction: it only handles a-    unidirectional flow of information.  If you want a bidirectional 'Pipe'-    type, then use the 'Proxy' type from "Control.Proxy", which generalizes the-    'Pipe' type to bidirectional flow.--    More importantly, the 'Proxy' type is a strict superset of the 'Pipe' type,-    so all 'Pipe' utilities and extensions are actually written as 'Proxy'-    utilities and extensions, in order to avoid code duplication.--    So if you want to use these extensions, import "Control.Proxy" instead,-    which exports a backwards compatible 'Pipe' implementation along with all-    utilities and extensions.  The 'Pipe' implementation in "Control.Pipe.Core"-    exists purely as a reference implementation for people who wish to study the-    simpler 'Pipe' type when building their own iteratee libraries.--}
Control/Proxy.hs view
@@ -1,32 +1,35 @@--- | Default imports for the "Control.Proxy" hierarchy+{-| Recommended entry import for this library +    Read "Control.Proxy.Tutorial" for an extended proxy tutorial. -}+ module Control.Proxy (     -- * Modules-    -- $modules-    module Control.Proxy.Class,+    -- $default     module Control.Proxy.Core,-    module Control.Proxy.Pipe,-    module Control.Proxy.Trans,-    module Control.Proxy.Prelude+    module Control.Proxy.Core.Fast     ) where -import Control.Proxy.Class import Control.Proxy.Core-import Control.Proxy.Pipe-import Control.Proxy.Trans-import Control.Proxy.Prelude+import Control.Proxy.Core.Fast hiding (Request, Respond, M, Pure) -{- $modules-    "Control.Proxy.Core" provides the core 'Proxy' type.+{- $default+    "Control.Proxy.Core" exports everything except 'runProxy'. -    "Control.Proxy.Class" provides the abstract interface to 'Proxy' operations.+    This library provides two base proxy implementations, each of which export+    their own 'runProxy' function: -    "Control.Proxy.Trans" provides proxy transformers.+    * "Control.Proxy.Core.Fast": This runs faster for code that is not+      'IO'-bound, but it only obeys the monad transformer laws modulo safe+      observation functions. -    "Control.Proxy.Pipe" provides a backwards-compatible re-implementation of-    'Pipe's.+    * "Control.Proxy.Core.Correct": This trades speed on pure code segments, but+       strictly preserves the monad transformer laws. -    "Control.Proxy.Prelude" provides a standard library of proxies.+    This module selects the currently recommended implementation (Fast). -    Consult "Control.Proxy.Tutorial" for an extended tutorial.+    You can switch to the correct implementation by importing+    "Control.Proxy.Core" and "Control.Proxy.Core.Correct".++    You can lock in the fast implementation (in case I change the recommended+    default) by importing "Control.Proxy.Core" and "Control.Proxy.Core.Fast". -}
Control/Proxy/Class.hs view
@@ -1,72 +1,308 @@-{-| This module provides an abstract interface to 'Proxy'-like behavior, so that-    multiple proxy implementations can share the same library of utility-    proxies. -}+{-# LANGUAGE Rank2Types #-} +{-| The 'Proxy' class defines the library's core API.  Everything else in this+    library builds exclusively on top of the 'Proxy' type class so that all+    proxy implementations and extensions can share the same standard library.++    Several of these type classes duplicate methods from familiar type-classes+    (such as ('?>=') duplicating ('>>=')).  You do NOT need to use these+    duplicate methods.  Instead, read the \"Polymorphic proxies\" section below+    which explains their purpose and how they help clean up type signatures. -}+ module Control.Proxy.Class (-    -- * Proxy composition-    Channel(..),-    -- * Proxy request and respond+    -- * Core proxy class+    Proxy(..),+    idT,+    coidT,+    (<-<),+    (<~<),++    -- * request/respond substitution     Interact(..),+    (/</),+    (\<\),++    -- * Laws+    -- $laws++    -- * Polymorphic proxies+    -- $poly+    MonadPlusP(..),+    MonadIOP(..)     ) where -{- * I use educated guesses about which associativy is optimal for each operator-   * Keep precedence lower than function composition, which is 9 at the time of-     of this comment -}+import Control.Monad.IO.Class (MonadIO)++-- Documentation imports+import Control.Monad.Trans.Class (lift)+import Control.MFunctor(hoist)++{- * I make educated guesses about which associativy is most efficient for each+     operator.+   * Keep proxy composition lower in precedence than function composition, which+     is 9 at the time of of this comment, so that users can write things like:++> lift . k >-> p+>+> hoist f . k >-> p+-} infixr 7 <-< infixl 7 >-> infixr 8 /</ infixl 8 \>\ infixl 8 \<\ infixr 8 />/+infixl 1 ?>= -- This should match the fixity of >>= -{-| The 'Channel' class defines an interface to a bidirectional flow of-    information.+{-| The core API for the @pipes@ library -    Laws:+    You should only use 'request', 'respond', and ('>->') +    I only provide ('>~>') for theoretical symmetry, and the remaining methods+    just implement internal type class plumbing.+-}+class Proxy p where+    {-| 'request' input from upstream, passing an argument with the request++        @request a'@ passes @a'@ as a parameter to upstream that upstream may+        use to decide what response to return.  'request' binds the upstream's+        response of type @a@ to its own return value. -}+    request :: (Monad m) => a' -> p a' a b' b m a++    {-| 'respond' with an output for downstream and bind downstream's next+        'request'+          +        @respond b@ satisfies a downstream 'request' by supplying the value @b@.+        'respond' blocks until downstream 'request's a new value and binds the+        argument of type @b'@ from the next 'request' as its return value. -}+    respond :: (Monad m) => b -> p a' a b' b m b'++    {-| Compose two proxies blocked on a 'respond', generating a new proxy+        blocked on a 'respond'++        Begins from the downstream end and satisfies every 'request' with a+        'respond' -}+    (>->)+     :: (Monad m)+     => (b' -> p a' a b' b m r)+     -> (c' -> p b' b c' c m r)+     -> (c' -> p a' a c' c m r)++    {-| Compose two proxies blocked on a 'request', generating a new proxy+        blocked on a 'request'++        Begins from the upstream end and satisfies every 'respond' with a+        'request' -}+    (>~>)+     :: (Monad m)+     => (a -> p a' a b' b m r)+     -> (b -> p b' b c' c m r)+     -> (a -> p a' a c' c m r)++    {-| 'return_P' is identical to 'return', except with a more polymorphic+        constraint. -}+    return_P :: (Monad m) => r -> p a' a b' b m r++    {-| ('?>=') is identical to ('>>='), except with a more polymorphic+        constraint. -}+    (?>=)+     :: (Monad m)+     => p a' a b' b m r -> (r -> p a' a b' b m r') -> p a' a b' b m r'++    {-| 'lift_P' is identical to 'lift', except with a more polymorphic+        constraint. -}+    lift_P :: (Monad m) => m r -> p a' a b' b m r++    {-| 'hoist_P' is identical to 'hoist', except with a more polymorphic+        constraint. -}+    hoist_P+     :: (Monad m)+     => (forall r . m r  -> n r) -> (p a' a b' b m r' -> p a' a b' b n r')++{-| 'idT' forwards requests followed by responses++> idT = request >=> respond >=> idT+-}+idT :: (Monad m, Proxy p) => a' -> p a' a a' a m r+idT = go where+    go a' =+        request a' ?>= \a   ->+        respond a  ?>= \a'2 ->+        go a'2+-- idT = foreverK $ request >=> respond++{-| 'coidT' forwards responses followed by requests++> coidT = respond >=> request >=> coidT+-}+coidT :: (Monad m, Proxy p) => a -> p a' a a' a m r+coidT = go where+    go a =+        respond a  ?>= \a' ->+        request a' ?>= \a2 ->+        go a2+-- coidT = foreverK $ respond >=> request++{-| Compose two proxies blocked on a 'respond', generating a new proxy blocked+    on a 'respond'++    Begins from the downstream end and satisfies every 'request' with a+    'respond' -}+(<-<)+ :: (Monad m, Proxy p)+ => (c' -> p b' b c' c m r)+ -> (b' -> p a' a b' b m r)+ -> (c' -> p a' a c' c m r)+p1 <-< p2 = p2 >-> p1++{-| Compose two proxies blocked on a 'request', generating a new proxy blocked+    on a 'request'++    Begins from the upstream end and satisfies every 'respond' with a 'request'++    You don't need to use this.  I include it only for symmetry. -}+(<~<)+ :: (Monad m, Proxy p)+ => (b -> p b' b c' c m r)+ -> (a -> p a' a b' b m r)+ -> (a -> p a' a c' c m r)+p1 <~< p2 = p2 >~> p1++-- | Two extra Proxy categories of theoretical interest+class Interact p where+    -- | @f \\>\\ g@ replaces all 'request's in 'g' with 'f'.+    (\>\) :: (Monad m)+          => (b' -> p a' a x' x m b)+          -> (c' -> p b' b x' x m c)+          -> (c' -> p a' a x' x m c)++    -- | @f \/>\/ g@ replaces all 'respond's in 'f' with 'g'.+    (/>/) :: (Monad m)+          => (a -> p x' x b' b m a')+          -> (b -> p x' x c' c m b')+          -> (a -> p x' x c' c m a')++-- | @f \/<\/ g@ replaces all 'request's in 'f' with 'g'.+(/</) :: (Monad m, Interact p)+      => (c' -> p b' b x' x m c)+      -> (b' -> p a' a x' x m b)+      -> (c' -> p a' a x' x m c)+p1 /</ p2 = p2 \>\ p1++-- | @f \\<\\ g@ replaces all 'respond's in 'g' with 'f'.+(\<\) :: (Monad m, Interact p)+      => (b -> p x' x c' c m b')+      -> (a -> p x' x b' b m a')+      -> (a -> p x' x c' c m a')+p1 \<\ p2 = p2 />/ p1++{- $laws+    The 'Proxy' class defines an interface to all core proxy capabilities that+    all proxy-like types must implement.++    First, all proxies must support a bidirectional flow of information, defined+    by:++    * ('>->')++    * ('>~>')++    * 'request'++    * 'respond'++    Intuitively, both @p1 >-> p2@ and @p1 >~> p2@ pair each 'request' in @p2@+    with a 'respond' in @p1@.  ('>->') accepts proxies blocked on 'respond' and+    begins from the downstream end, whereas ('>~>') accepts proxies blocked on+    'request' and begins from the upstream end.++    Second, all proxies are monads, defined by:++    * 'return_P'++    * ('?>=')++    These must satify the monad laws using @(>>=) = (?>=)@ and+    @return = return_P@.++    Third, all proxies are monad transformers, defined by:++    * 'lift_P'++    This must satisfy the monad transformer laws, using @lift = lift_P@.++    Fourth, all proxies are functors in the category of monads, defined by:++    * 'hoist_P'++    This must satisfy the functor laws, using @hoist = hoist_P@.++    All 'Proxy' instances must satisfy these additional laws:+     * ('>->') and 'idT' form a category: -> idT >-> f = f+> Define: idT = request >=> respond >=> idT >-> f >-> idT = f+> idT >-> p = p >-> (f >-> g) >-> h = f >-> (g >-> h)+> p >-> idT = p+>+> (p1 >-> p2) >-> p3 = p1 >-> (p2 >-> p3) -    Minimal complete definition:+    * ('>~>') and 'coidT' form a category: -    * 'idT'+> Define: coidT = respond >=> request >=> coidT+>+> coidT >~> p = p+>+> p >~> coidT = p+>+> (p1 >~> p2) >~> p3 = p1 >~> (p2 >~> p3) -    * ('>->') or ('<-<').--}-class Channel p where-    {-| 'idT' acts like a \'T\'ransparent proxy, passing all requests further-        upstream, and passing all responses further downstream. -}-    idT :: (Monad m) => a' -> p a' a a' a m r+    * @(hoistK f)@ defines a functor between proxy categories: -    {-| Compose two proxies, satisfying all requests from downstream with-        responses from upstream. -}-    (>->) :: (Monad m)-          => (b' -> p a' a b' b m r)-          -> (c' -> p b' b c' c m r)-          -> (c' -> p a' a c' c m r)-    p1 >-> p2 = p2 <-< p1+> Define: hoistK f = (hoist f .)+>+> hoistK f (p1 >-> p2) = hoistK f p1 >-> hoistK p2+>+> hoistK f idT = idT+>+> hoistK f (p1 >~> p2) = hoistK f p1 >~> hoistK p2+>+> hoistK f coidT = coidT -    {-| Compose two proxies, satisfying all requests from downstream with-        responses from upstream. -}-    (<-<) :: (Monad m)-          => (c' -> p b' b c' c m r)-          -> (b' -> p a' a b' b m r)-          -> (c' -> p a' a c' c m r)-    p1 <-< p2 = p2 >-> p1+    Also, all proxies must satisfy the following 'Proxy' laws: -{-| The 'Interact' class defines the ability to:+> -- Define: liftK = (lift .)+>+> p1 >-> liftK f = liftK f+>+> p1 >-> (liftK f >=> respond >=> p2) = liftK f >=> respond >=> (p1 >-> p2)+>+> (liftK g >=> respond >=> p1) >-> (liftK f >=> request >=> liftK h >=> p2)+>     = liftK (f >=> g >=> h) >=> (p1 >-> p2)+>+> (liftK g >=> request >=> p1) >-> (liftK f >=> request >=> p2)+>     = liftK (f >=> g) >=> request >=> (p1 >~> p2)+>+> liftK f >~> p2 = liftK f+>+> (liftK f >=> request >=> p1) >~> p2 = liftK f >=> request >=> (p1 >~> p2)+>+> (liftK f >=> respond >=> liftK h >=> p1) >~> (liftK g >=> request >=> p2)+>     = liftK (f >=> g >=> h) >=> (p1 >~> p2)+>+> (liftK f >=> respond >=> p1) >~> (liftK g >=> respond >=> p2)+>     = liftK (f >=> g) >=> (p1 >-> p2) -    * Request input using the 'request' command+    The 'Interact' class exists primarily for theoretical interest and to+    justify some of the functor laws for the 'ProxyTrans' type class.  You will+    probably never use it. +    The 'Interact' class defines the ability to:+         * Replace existing 'request' commands using ('\>\') -    * Respond with output using the 'respond' command-     * Replace existing 'respond' commands using ('/>/')          Laws:@@ -87,56 +323,130 @@ > > (f />/ g) />/ h = f />/ (g />/ h) -    Minimal complete definition:+    Additionally, ('\>\') and ('/>/') distribute in one direction over Kleisli+    composition: -    * 'request',+> a \>\ (b >=> c) = (a \>\ b) >=> (a \>\ c)+>+> a \>\ return = return -    * ('\>\') or ('/</'),+> (b >=> c) />/ a = (b />/ a) >=> (c />/ a)+>+> return />/ a = return+-} -    * 'respond', and+{- $poly+    Many of these type classes contain methods which copy methods from more+    familiar type classes.  These duplicate methods serve two purposes. -    * ('/>/') or ('\<\').--}-class Interact p where-    {-| 'request' input from upstream, passing an argument with the request+    First, this library requires type class instances that would otherwise be+    impossible to define without providing higher-kinded constraints.  Rather+    than use the following illegal polymorphic constraint: -        @request a'@ passes @a'@ as a parameter to upstream that upstream may-        use to decide what response to return.  'request' binds the upstream's-        response to its own return value. -}-    request :: (Monad m) => a' -> p a' a x' x m a+> instance (forall a' a b' b . MonadTrans (p a' a b' b)) => ... -    -- | @f \\>\\ g@ replaces all 'request's in 'g' with 'f'.-    (\>\) :: (Monad m)-          => (b' -> p a' a x' x m b)-          -> (c' -> p b' b x' x m c)-          -> (c' -> p a' a x' x m c)-    p1 \>\ p2 = p2 /</ p1+      ... the instance can instead use the following Haskell98 constraint: -    -- | @f \/<\/ g@ replaces all 'request's in 'f' with 'g'.-    (/</) :: (Monad m)-          => (c' -> p b' b x' x m c)-          -> (b' -> p a' a x' x m b)-          -> (c' -> p a' a x' x m c)-    p1 /</ p2 = p2 \>\ p1+> instance (MonadTransP p) => ... -    {-| 'respond' with an output for downstream and bind downstream's next-        'request'-          -        @respond b@ satisfies a downstream 'request' by supplying the value @b@-        'respond' blocks until downstream 'request's a new value and binds the-        argument from the next 'request' as its return value. -}-    respond :: (Monad m) => a -> p x' x a' a m a'+    Second, these type classes don't require the @FlexibleContexts@ extension+    to use and substantially clean up constraints in type signatures.  They+    convert messy constraints like this: -    -- | @f \/>\/ g@ replaces all 'respond's in 'f' with 'g'.-    (/>/) :: (Monad m)-          => (a -> p x' x b' b m a')-          -> (b -> p x' x c' c m b')-          -> (a -> p x' x c' c m a')-    p1 />/ p2 = p2 \<\ p1+> p :: (MonadP (p a' a b' b m), MonadTrans (p a' a b' b)) => ... -    -- | @f \\<\\ g@ replaces all 'respond's in 'g' with 'f'.-    (\<\) :: (Monad m)-          => (b -> p x' x c' c m b')-          -> (a -> p x' x b' b m a')-          -> (a -> p x' x c' c m a')-    p1 \<\ p2 = p2 />/ p1+      .. into cleaner and more general constraints like this:++> P :: (Proxy p) => ...++    These type classes exist solely for internal plumbing and you should never+    directly use the duplicate methods from them.  Instead, you can use all the+    original type classes as long as you embed your proxy code within at least+    one proxy transformer (or 'IdentityP' if don't use any transformers).  The+    type-class machinery will then automatically convert the messier and less+    polymorphic constraints to the simpler and more general constraints.++    For example, consider the following almost-correct definition for @mapMD@+    (from "Control.Proxy.Prelude.Base"):++> import Control.Monad.Trans.Class+> import Control.Proxy+>+> mapMD f = foreverK $ \a' -> do+>     a <- request a'+>     b <- lift (f a)+>     respond b++    The compiler infers the following messy constraint:++> mapMD+>  :: (Monad m, Monad (p x a x b m), MonadTrans (p x a x b), Proxy p)+>  => (a -> m b) -> x -> p x a x b m r++    Instead, you can embed the code in the @IdentityP@ proxy transformer by+    wrapping it in 'runIdentityK':++> --        |difference|  +> mapMD f = runIdentityK $ foreverK $ \a' -> do+>     a <- request a'+>     b <- lift (f a)+>     respond b++    ... and now the compiler collapses all the constraints into the 'Proxy'+    constraint:++> mapMD :: (Monad m, Proxy p) => (a -> m b) -> x -> p x a x b m r++    You do not incur any performance penalty for writing polymorphic code or+    embedding it in 'IdentityP'.  This library employs several rewrite @RULES@+    which transform your polymorphic code into the equivalent type-specialized+    hand-tuned code.  These rewrite rules fire very robustly and they do not+    require any assistance on your part from compiler pragmas like @INLINE@,+    @NOINLINE@ or @SPECIALIZE@.++    If you nest proxies within proxies:++> example () = do+>     request ()+>     lift $ request ()+>     lift $ lift $ request ()++    ... then you can still keep the nice constraints using:++> example () = runIdentityP . hoist (runIdentityP . hoist runIdentityP) $ do+>     request ()+>     lift $ request ()+>     lift $ lift $ request ()++    You don't need to use 'runIdentityP' \/ 'runIdentityK' if you use any other+    proxy transformers (In fact you can't, it's a type error).  The following+    code example illustrates this, where the 'throw' command (from the 'EitherP'+    proxy transformer) suffices to guide the compiler to the cleaner type+    signature:++> import Control.Monad+> import Control.Proxy+> import qualified Control.Proxy.Trans.Either as E+>+> example :: (Monad m, Proxy p) => () -> Producer (EitherP String p) Char m ()+> example () = do+>     c <- request ()+>     when (c == ' ') $ E.throw "Error: received space"+>     respond c+-}++{-| The @(MonadPlusP p)@ constraint is equivalent to the following constraint:++> (forall a' a b' b m . (Monad m) => MonadPlus (p a' a b' b m)) => ...+-}+class (Proxy p) => MonadPlusP p where+    mzero_P :: (Monad m) => p a' a b' b m r+    mplus_P+     :: (Monad m) => p a' a b' b m r -> p a' a b' b m r -> p a' a b' b m r++{-| The @(MonadIOP p)@ constraint is equivalent to the following constraint:++> (forall a' a b' b m . (MonadIO m) => MonadIO (p a' a b' b m)) => ...+-}+class (Proxy p) => MonadIOP p where+    liftIO_P :: (MonadIO m) => IO r -> p a' a b' b m r
Control/Proxy/Core.hs view
@@ -1,217 +1,45 @@-{-| A 'Proxy' 'request's input from upstream and 'respond's with output to-    downstream.--    For an extended tutorial, consult "Control.Proxy.Tutorial". -}+-- | Default imports for the "Control.Proxy" hierarchy  module Control.Proxy.Core (-    -- * Types-    Proxy(..),-    C,-    Server,-    Client,-    Session,-    -- * Run Sessions -    -- $run-    runProxy,-    runProxyK,-    runSession,-    runSessionK,-    -- * Utility Proxies-    -- $utility-    discard,-    ignore+    -- * Modules+    -- $modules+    module Control.Proxy.Class,+    module Control.Proxy.Synonym,+    module Control.Proxy.Prelude,+    module Control.Proxy.Trans,+    module Control.Proxy.Trans.Identity,+    module Control.Monad,+    module Control.Monad.Trans.Class,+    module Control.MFunctor     ) where -import Control.Applicative (Applicative(pure, (<*>)))-import Control.Monad (ap, forever, liftM, (>=>))-import Control.Monad.IO.Class (MonadIO(liftIO))+import Control.MFunctor (MFunctor(hoist))+import Control.Monad (forever, (>=>), (<=<)) import Control.Monad.Trans.Class (MonadTrans(lift))-import Control.MFunctor (MFunctor(mapT))-import Control.Proxy.Class (-    Channel(idT, (<-<)), Interact(request, (/</), respond, (\<\)) )-import Data.Closed (C)--{-| A 'Proxy' communicates with an upstream interface and a downstream-    interface.--    The type variables of @Proxy req_a resp_a req_b resp_b m r@ signify:--    * @req_a @ - The request supplied to the upstream interface--    * @resp_a@ - The response provided by the upstream interface--    * @req_b @ - The request supplied by the downstream interface--    * @resp_b@ - The response provided to the downstream interface--    * @m     @ - The base monad--    * @r     @ - The final return value -}-data Proxy a' a b' b m r-  = Request a' (a  -> Proxy a' a b' b m r )-  | Respond b  (b' -> Proxy a' a b' b m r )-  | M          (m    (Proxy a' a b' b m r))-  | Pure r--instance (Monad m) => Functor (Proxy a' a b' b m) where-    fmap f p0 = go p0 where-        go p = case p of-            Request a' fa  -> Request a' (\a  -> go (fa  a ))-            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))-            M          m   -> M (m >>= \p' -> return (go p'))-            Pure       r   -> Pure (f r)--instance (Monad m) => Applicative (Proxy a' a b' b m) where-    pure  = Pure-    pf <*> px = go pf where-        go p = case p of-            Request a' fa  -> Request a' (\a  -> go (fa  a ))-            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))-            M          m   -> M (m >>= \p' -> return (go p'))-            Pure       f   -> fmap f px--instance (Monad m) => Monad (Proxy a' a b' b m) where-    return = Pure-    p0 >>= f = go p0 where-        go p = case p of-            Request a' fa  -> Request a' (\a  -> go (fa  a))-            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))-            M m            -> M (m >>= \p' -> return (go p'))-            Pure r         -> f r--instance MonadTrans (Proxy a' a b' b) where-    lift = M . liftM Pure--instance (MonadIO m) => MonadIO (Proxy a' a b' b m) where-    liftIO = M . liftIO . liftM Pure--instance Channel Proxy where-    idT = \a' -> Request a' $ \a -> Respond a idT-    k1 <-< k2_0 = \c' -> k1 c' |-< k2_0 where-        p1 |-< k2 = case p1 of-            Request b' fb  -> fb <-| k2 b'-            Respond c  fc' -> Respond c (\c' -> fc' c' |-< k2)-            M          m   -> M (m >>= \p1' -> return (p1' |-< k2))-            Pure       r   -> Pure r-        fb <-| p2 = case p2 of-            Request a' fa  -> Request a' (\a -> fb <-| fa a) -            Respond b  fb' -> fb b |-< fb'-            M          m   -> M (m >>= \p2' -> return (fb <-| p2'))-            Pure       r   -> Pure r--instance Interact Proxy where-    request a' = Request a' Pure-    k1 /</ k2 = \a' -> go (k1 a') where-        go p = case p of-            Request b' fb  -> k2 b' >>= \b -> go (fb b)-            Respond x  fx' -> Respond x (\x' -> go (fx' x'))-            M          m   -> M (m >>= \p' -> return (go p'))-            Pure       a   -> Pure a-    respond a = Respond a Pure-    k1 \<\ k2 = \a' -> go (k2 a') where-        go p = case p of-            Request x' fx  -> Request x' (\x -> go (fx x))-            Respond b  fb' -> k1 b >>= \b' -> go (fb' b')-            M          m   -> M (m >>= \p' -> return (go p'))-            Pure       a   -> Pure a--instance MFunctor (Proxy a' a b' b) where-    mapT nat p0 = go p0 where-        go p = case p of-            Request a' fa  -> Request a' (\a  -> go (fa  a ))-            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))-            M          m   -> M (nat (m >>= \p' -> return (go p')))-            Pure       r   -> Pure r--{-| @Server req resp@ receives requests of type @req@ and sends responses of-    type @resp@.--    'Server's only 'respond' and never 'request' anything. -}-type Server req resp = Proxy C   ()   req resp--{-| @Client req resp@ sends requests of type @req@ and receives responses of-    type @resp@.--    'Client's only 'request' and never 'respond' to anything. -}-type Client req resp = Proxy req resp ()  C--{-| A self-contained 'Session', ready to be run by 'runSession'--    'Session's never 'request' anything or 'respond' to anything. -}-type Session         = Proxy C   ()   ()  C--{- $run-    I provide two ways to run proxies:--    * 'runProxy', which discards unhandled output from either end--    * 'runSession', which type restricts its argument to ensure no loose ends--    Both functions require that the input to each end is trivially satisfiable,-    (i.e. @()@).--    I recommend 'runProxy' for most use cases since it is more convenient.--    'runSession' only accepts sessions that do not send unhandled data flying-    off each end, which provides the following benefits:--    * It prevents against accidental data loss.--    * It protects against silent failures--    * It prevents wastefully draining a scarce resource by gratuitously-      driving it to completion--    However, this restriction means that you must either duplicate every utility-    function to specialize them to the end-point positions (which I do not do),-    or explicitly close loose ends using the 'discard' and 'ignore' proxies:+import Control.Proxy.Class+import Control.Proxy.Synonym+import Control.Proxy.Trans+import Control.Proxy.Trans.Identity+import Control.Proxy.Prelude -> runSession $ discard <-< p <-< ignore+{- $modules+    "Control.Proxy.Class" defines the 'Proxy' type class that lets you program+    generically over proxy implementations and their transformers. -    Use the \'@K@\' versions of each command if you are running sessions nested-    within sessions.  They provide a Kleisli arrow as their result suitable to-    be passed to another 'runProxy' / 'runSession' command.--}+    "Control.Proxy.Synonym" defines type synonyms for proxies that don't use all+    of their inputs or outputs, such as 'Pipe's, 'Producer's, and 'Server's. -{-| Run a self-sufficient 'Proxy' Kleisli arrow, converting it back to the base-    monad -}-runProxy :: (Monad m) => (() -> Proxy a' () () b m r) -> m r-runProxy k = go (k ()) where-    go p = case p of-        Request _ fa  -> go (fa  ())-        Respond _ fb' -> go (fb' ())-        M         m   -> m >>= go-        Pure      r   -> return r+    "Control.Proxy.Prelude" provides a standard library of proxies. -{-| Run a self-sufficient 'Proxy' Kleisli arrow, converting it back to a Kleisli-    arrow in the base monad -}-runProxyK :: (Monad m) => (() -> Proxy a () () b m r) -> (() -> m r)-runProxyK p = \() -> runProxy p+    "Control.Proxy.Trans" defines the 'ProxyTrans' type class that lets you+    write your own proxy extensions. -{-| Run a self-contained 'Session' Kleisli arrow, converting it back to the base-    monad -}-runSession :: (Monad m) => (() -> Session m r) -> m r-runSession = runProxy+    "Control.Proxy.Trans.Identity" exports 'runIdentityP', which substantially+    eases writing completely polymorphic proxies. -{-| Run a self-contained 'Session' Kleisli arrow, converting it back to a-    Kleisli arrow in the base monad -}-runSessionK :: (Monad m) => (() -> Session m r) -> (() -> m r)-runSessionK = runProxyK+    "Control.Monad" exports 'forever', ('>=>'), and ('<=<'). -{- $utility-    'discard' provides a fallback client that gratuitously 'request's input-    from a server, but discards all responses.+    "Control.Monad.Trans.Class" exports 'lift'. -    'ignore' provides a fallback server that trivially 'respond's with output-    to a client, but ignores all request parameters.+    "Control.MFunctor" exports 'hoist'. -}---- | Discard all responses-discard :: (Monad m) => () -> Proxy () a () C m r-discard _ = go where-    go = Request () (\_ -> go)---- | Ignore all requests-ignore  :: (Monad m) => a -> Proxy C () a () m r-ignore _ = go where-    go = Respond () (\_ -> go)
+ Control/Proxy/Core/Correct.hs view
@@ -0,0 +1,186 @@+{-| This module provides the correct proxy implementation which strictly+    enforces the monad transformer laws.  You can safely import this module+    without violating any laws or invariants.++    However, I advise that you stick to the 'Proxy' type class API rather than+    import this module so that your code works with both 'Proxy' implementations+    and also works with all proxy transformers. -}++module Control.Proxy.Core.Correct (+    -- * Types+    ProxyCorrect(..),+    ProxyF(..),++    -- * Run Sessions +    -- $run+    runProxy,+    runProxyK,+    runPipe+    ) where++import Control.Applicative (Applicative(pure, (<*>)))+import Control.Monad.IO.Class (MonadIO(liftIO))+import Control.Monad.Trans.Class (MonadTrans(lift))+import Control.MFunctor (MFunctor(hoist))+import Control.Proxy.Class+import Control.Proxy.Synonym (C)++{-| A 'ProxyCorrect' communicates with an upstream interface and a downstream+    interface.++    The type variables of @ProxyCorrect req_a' resp_a req_b' resp_b m r@+    signify:++    * @req_a'@ - The request supplied to the upstream interface++    * @resp_a@ - The response provided by the upstream interface++    * @req_b'@ - The request supplied by the downstream interface++    * @resp_b@ - The response provided to the downstream interface++    * @m     @ - The base monad++    * @r     @ - The final return value -}+data ProxyCorrect a' a b' b m  r =+    Proxy { unProxy :: m (ProxyF a' a b' b r (ProxyCorrect a' a b' b m r)) }++-- | The base functor for the 'ProxyCorrect' type+data ProxyF a' a b' b r x+  = Request a' (a  -> x)+  | Respond b  (b' -> x)+  | Pure    r++instance (Monad m) => Functor (ProxyCorrect a' a b' b m) where+    fmap f p0 = go p0 where+        go p = Proxy (do+            x <- unProxy p+            return (case x of+                Request a' fa  -> Request a' (\a  -> go (fa  a ))+                Respond b  fb' -> Respond b  (\b' -> go (fb' b'))+                Pure       r   -> Pure (f r) ) )++instance (Monad m) => Applicative (ProxyCorrect a' a b' b m) where+    pure r = Proxy (return (Pure r))+    pf <*> px = go pf where+        go p = Proxy (do+            x <- unProxy p+            case x of+                Request a' fa  -> return (Request a' (\a  -> go (fa  a )))+                Respond b  fb' -> return (Respond b  (\b' -> go (fb' b')))+                Pure       f   -> unProxy (fmap f px) )++instance (Monad m) => Monad (ProxyCorrect a' a b' b m) where+    return = \r -> Proxy (return (Pure r))+    p0 >>= f = go p0 where+        go p = Proxy (do+            x <- unProxy p+            case x of+                Request a' fa  -> return (Request a' (\a  -> go (fa  a )))+                Respond b  fb' -> return (Respond b  (\b' -> go (fb' b')))+                Pure       r   -> unProxy (f r) )++instance MonadTrans (ProxyCorrect a' a b' b) where+    lift = lift_P++instance (MonadIO m) => MonadIO (ProxyCorrect a' a b' b m) where+    liftIO m = Proxy (liftIO (m >>= \r -> return (Pure r)))+ -- liftIO = Proxy . liftIO . liftM Pure++instance MonadIOP ProxyCorrect where+    liftIO_P = liftIO++instance Proxy ProxyCorrect where+    fb'_0 >-> fc' = \c' -> fb'_0 >-| fc' c' where+        fb' >-| p1 = Proxy (do+            x <- unProxy p1+            case x of+                Request b' fb  -> unProxy (fb' b' |-> fb)+                Respond c  fc' -> return (Respond c (\c' -> fb' >-| fc' c'))+                Pure       r   -> return (Pure r) )+        p2 |-> fb = Proxy (do+            x <- unProxy p2+            case x of+                Request a' fa  -> return (Request a' (\a -> fa a |-> fb))+                Respond b  fb' -> unProxy (fb' >-| fb b)+                Pure       r   -> return (Pure r) )++    fa_0 >~> fb_0 = \a -> fa_0 a |-> fb_0 where+        fb' >-| p1 = Proxy (do+            x <- unProxy p1+            case x of+                Request b' fb  -> unProxy (fb' b' |-> fb)+                Respond c  fc' -> return (Respond c (\c' -> fb' >-| fc' c'))+                Pure       r   -> return (Pure r) )+        p2 |-> fb = Proxy (do+            x <- unProxy p2+            case x of+                Request a' fa  -> return (Request a' (\a -> fa a |-> fb))+                Respond b  fb' -> unProxy (fb' >-| fb b)+                Pure       r   -> return (Pure r) )++    request a' = Proxy (return (Request a' (\a  -> Proxy (return (Pure a )))))+    respond b  = Proxy (return (Respond b  (\b' -> Proxy (return (Pure b')))))++    return_P = return+    (?>=)   = (>>=)++    lift_P m = Proxy (m >>= \r -> return (Pure r))++    hoist_P = hoist++instance Interact ProxyCorrect where+    k2 \>\ k1 = \a' -> go (k1 a') where+        go p = Proxy (do+            x <- unProxy p+            case x of+                Request b' fb  -> unProxy (k2 b' >>= \b -> go (fb b))+                Respond x  fx' -> return (Respond x (\x' -> go (fx' x')))+                Pure       a   -> return (Pure a) )+    k2 />/ k1 = \a' -> go (k2 a') where+        go p = Proxy (do+            x <- unProxy p+            case x of+                Request x' fx  -> return (Request x' (\x -> go (fx x)))+                Respond b  fb' -> unProxy (k1 b >>= \b' -> go (fb' b'))+                Pure       a   -> return (Pure a) )++instance MFunctor (ProxyCorrect a' a b' b) where+    hoist nat p0 = go p0 where+        go p = Proxy (nat (do+            x <- unProxy p+            return (case x of+                Request a' fa  -> Request a' (\a  -> go (fa  a ))+                Respond b  fb' -> Respond b  (\b' -> go (fb' b'))+                Pure       r   -> Pure r )))++{- $run+    The following commands run self-sufficient proxies, converting them back to+    the base monad.++    These are the only functions specific to the 'ProxyCorrect' type.+    Everything else programs generically over the 'Proxy' type class.++    Use 'runProxyK' if you are running proxies nested within proxies.  It+    provides a Kleisli arrow as its result that you can pass to another+    'runProxy' / 'runProxyK' command. -}++{-| Run a self-sufficient 'ProxyCorrect' Kleisli arrow, converting it back to+    the base monad -}+runProxy :: (Monad m) => (() -> ProxyCorrect a' () () b m r) -> m r+runProxy k = go (k ()) where+    go p = do+        x <- unProxy p+        case x of+            Request _ fa  -> go (fa  ())+            Respond _ fb' -> go (fb' ())+            Pure      r   -> return r++{-| Run a self-sufficient 'ProxyCorrect' Kleisli arrow, converting it back to a+    Kleisli arrow in the base monad -}+runProxyK :: (Monad m) => (() -> ProxyCorrect a' () () b m r) -> (() -> m r)+runProxyK p = \() -> runProxy p++-- | Run the 'Pipe' monad transformer, converting it back to the base monad+runPipe :: (Monad m) => ProxyCorrect a' () () b m r -> m r+runPipe p = runProxy (\_ -> p)
+ Control/Proxy/Core/Fast.hs view
@@ -0,0 +1,238 @@+{-| This is an internal module, meaning that it is unsafe to import unless you+    understand the risks.++    This module provides the fast proxy implementation, which achieves its speed+    by weakening the monad transformer laws.  These laws do not hold if you can+    pattern match on the constructors, as the following counter-example+    illustrates:++> lift . return = M . return . Pure+>+> return = Pure+>+> lift . return /= return++    These laws only hold when viewed through certain safe observation functions,+    like 'runProxy' and 'observe'.++    Also, you really should not use the constructors anyway, let alone the+    concrete type and instead you should stick to the 'Proxy' type class API.+    This not only ensures that your code does not violate the monad transformer+    laws, but also guarantees that it works with the other proxy implementations+    and with any proxy transformers. -}++module Control.Proxy.Core.Fast (+    -- * Types+    ProxyFast(..),++    -- * Run Sessions +    -- $run+    runProxy,+    runProxyK,+    runPipe,++    -- * Safety+    observe+    ) where++import Control.Applicative (Applicative(pure, (<*>)))+-- import Control.Monad (ap, forever, liftM, (>=>))+import Control.Monad.IO.Class (MonadIO(liftIO))+import Control.Monad.Trans.Class (MonadTrans(lift))+import Control.MFunctor (MFunctor(hoist))+import Control.Proxy.Class+import Control.Proxy.Synonym (C)++{-| A 'ProxyFast' communicates with an upstream interface and a downstream+    interface.++    The type variables of @ProxyFast req_a' resp_a req_b' resp_b m r@ signify:++    * @req_a'@ - The request supplied to the upstream interface++    * @resp_a@ - The response provided by the upstream interface++    * @req_b'@ - The request supplied by the downstream interface++    * @resp_b@ - The response provided to the downstream interface++    * @m     @ - The base monad++    * @r     @ - The final return value -}+data ProxyFast a' a b' b m r+  = Request a' (a  -> ProxyFast a' a b' b m r )+  | Respond b  (b' -> ProxyFast a' a b' b m r )+  | M          (m    (ProxyFast a' a b' b m r))+  | Pure    r++instance (Monad m) => Functor (ProxyFast a' a b' b m) where+    fmap f p0 = go p0 where+        go p = case p of+            Request a' fa  -> Request a' (\a  -> go (fa  a ))+            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))+            M          m   -> M (m >>= \p' -> return (go p'))+            Pure       r   -> Pure (f r)++instance (Monad m) => Applicative (ProxyFast a' a b' b m) where+    pure      = Pure+    pf <*> px = go pf where+        go p = case p of+            Request a' fa  -> Request a' (\a  -> go (fa  a ))+            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))+            M          m   -> M (m >>= \p' -> return (go p'))+            Pure       f   -> fmap f px++instance (Monad m) => Monad (ProxyFast a' a b' b m) where+    return = Pure+    (>>=)  = _bind++_bind+ :: (Monad m)+ => ProxyFast a' a b' b m r+ -> (r -> ProxyFast a' a b' b m r')+ -> ProxyFast a' a b' b m r'+p0 `_bind` f = go p0 where+    go p = case p of+        Request a' fa  -> Request a' (\a  -> go (fa  a))+        Respond b  fb' -> Respond b  (\b' -> go (fb' b'))+        M          m   -> M (m >>= \p' -> return (go p'))+        Pure       r   -> f r++-- | Only satisfies laws modulo 'observe'+instance MonadTrans (ProxyFast a' a b' b) where+    lift = _lift++_lift :: (Monad m) => m r -> ProxyFast a' a b' b m r+_lift m = M (m >>= \r -> return (Pure r))+-- _lift = M . liftM Pure++{- These never fire, for some reason, but keep them until I figure out how to+   get them to work. -}+{-# RULES+    "_lift m ?>= f" forall m f .+        _bind (_lift m) f = M (m >>= \r -> return (f r))+  #-}++instance (MonadIO m) => MonadIO (ProxyFast a' a b' b m) where+    liftIO m = M (liftIO (m >>= \r -> return (Pure r)))+ -- liftIO = M . liftIO . liftM Pure++instance MonadIOP ProxyFast where+    liftIO_P = liftIO++instance Proxy ProxyFast where+    fb'_0 >-> fc'_0 = \c' -> fb'_0 >-| fc'_0 c' where+        p1 |-> fb = case p1 of+            Request a' fa  -> Request a' (\a -> fa a |-> fb)+            Respond b  fb' -> fb' >-| fb b+            M          m   -> M (m >>= \p1' -> return (p1' |-> fb))+            Pure       r   -> Pure r+        fb' >-| p2 = case p2 of+            Request b' fb  -> fb' b' |-> fb+            Respond c  fc' -> Respond c (\c' -> fb' >-| fc' c')+            M          m   -> M (m >>= \p2' -> return (fb' >-| p2'))+            Pure       r   -> Pure r++    fa_0 >~> fb_0 = \a -> fa_0 a |-> fb_0 where+        p1 |-> fb = case p1 of+            Request a' fa  -> Request a' (\a -> fa a |-> fb)+            Respond b  fb' -> fb' >-| fb b+            M          m   -> M (m >>= \p1' -> return (p1' |-> fb))+            Pure       r   -> Pure r+        fb' >-| p2 = case p2 of+            Request b' fb  -> fb' b' |-> fb+            Respond c  fc' -> Respond c (\c' -> fb' >-| fc' c')+            M          m   -> M (m >>= \p2' -> return (fb' >-| p2'))+            Pure       r   -> Pure r++    request a' = Request a' Pure+    respond b  = Respond b  Pure++    return_P = return+    (?>=)   = _bind++    lift_P = _lift++    hoist_P = hoist++{-# RULES+    "_bind (Request a' Pure) f" forall a' f .+        _bind (Request a' Pure) f = Request a' f;+    "_bind (Respond b  Pure) f" forall b  f .+        _bind (Respond b  Pure) f = Respond b  f+  #-}++instance Interact ProxyFast where+    k2 \>\ k1 = \a' -> go (k1 a') where+        go p = case p of+            Request b' fb  -> k2 b' >>= \b -> go (fb b)+            Respond x  fx' -> Respond x (\x' -> go (fx' x'))+            M          m   -> M (m >>= \p' -> return (go p'))+            Pure       a   -> Pure a+    k2 />/ k1 = \a' -> go (k2 a') where+        go p = case p of+            Request x' fx  -> Request x' (\x -> go (fx x))+            Respond b  fb' -> k1 b >>= \b' -> go (fb' b')+            M          m   -> M (m >>= \p' -> return (go p'))+            Pure       a   -> Pure a++instance MFunctor (ProxyFast a' a b' b) where+    hoist nat p0 = go (observe p0) where+        go p = case p of+            Request a' fa  -> Request a' (\a  -> go (fa  a ))+            Respond b  fb' -> Respond b  (\b' -> go (fb' b'))+            M          m   -> M (nat (m >>= \p' -> return (go p')))+            Pure       r   -> Pure r++{- $run+    The following commands run self-sufficient proxies, converting them back to+    the base monad.++    These are the only functions specific to the 'ProxyFast' type.  Everything+    else programs generically over the 'Proxy' type class.++    Use 'runProxyK' if you are running proxies nested within proxies.  It+    provides a Kleisli arrow as its result that you can pass to another+    'runProxy' / 'runProxyK' command. -}++{-| Run a self-sufficient 'ProxyFast' Kleisli arrow, converting it back to the+    base monad -}+runProxy :: (Monad m) => (() -> ProxyFast a' () () b m r) -> m r+runProxy k = go (k ()) where+    go p = case p of+        Request _ fa  -> go (fa  ())+        Respond _ fb' -> go (fb' ())+        M         m   -> m >>= go+        Pure      r   -> return r++{-| Run a self-sufficient 'ProxyFast' Kleisli arrow, converting it back to a+    Kleisli arrow in the base monad -}+runProxyK :: (Monad m) => (() -> ProxyFast a' () () b m r) -> (() -> m r)+runProxyK p = \() -> runProxy p++-- | Run the 'Pipe' monad transformer, converting it back to the base monad+runPipe :: (Monad m) => ProxyFast a' () () b m r -> m r+runPipe p = runProxy (\_ -> p)++{-| The monad transformer laws are correct when viewed through the 'observe'+    function:++> observe (lift (return r)) = observe (return r)+>+> observe (lift (m >>= f)) = observe (lift m >>= lift . f)++    This correctness comes at a moderate cost to performance, so use this+    function sparingly or else you would be better off using+    "Control.Proxy.Core.Correct".++    You do not need to use this function if you use the safe API exported from+    "Control.Proxy", which does not export any functions or constructors that+    can violate the monad transformer laws.+-}+observe :: (Monad m) => ProxyFast a' a b' b m r -> ProxyFast a' a b' b m r+observe p = M (go p) where+    go p = case p of+        M          m'  -> m' >>= go+        Pure       r   -> return (Pure r)+        Request a' fa  -> return (Request a' (\a  -> observe (fa  a )))+        Respond b  fb' -> return (Respond b  (\b' -> observe (fb' b')))
Control/Proxy/Pipe.hs view
@@ -1,90 +1,197 @@-{-| This module provides an API compatible with "Control.Pipe"+{-# LANGUAGE KindSignatures #-} -    Consult "Control.Pipe.Core" for more extensive documentation and-    "Control.Pipe.Tutorial" for an extended tutorial. -}+{-| This module provides an API similar to "Control.Pipe" for those who prefer+    the classic 'Pipe' API. +    This module differs slightly from "Control.Pipe" in order to promote+    seamless interoperability with both pipes and proxies.  See the \"Upgrade+    Pipes to Proxies\" section below for details. -} module Control.Proxy.Pipe (-    -- * Types-    Pipe,-    Producer,-    Consumer,-    Pipeline,     -- * Create Pipes     await,     yield,     pipe,+     -- * Compose Pipes     (<+<),     (>+>),     idP,-    -- * Run Pipes-    runPipe-    ) where -import Control.Proxy.Core-import Control.Proxy.Class-import Data.Closed (C)--{-| The type variables of @Pipe a b m r@ signify:--    * @a@ - The type of input received from upstream pipes--    * @b@ - The type of output delivered to downstream pipes--    * @m@ - The base monad--    * @r@ - The type of the return value -}-type Pipe   a b = Proxy () a () b+    -- * Synonyms+    Pipeline, --- | A pipe that produces values-type Producer b = Pipe () b+    -- * Run Pipes+    -- $run --- | A pipe that consumes values-type Consumer a = Pipe a  C+    -- * Upgrade Pipes to Proxies+    -- $upgrade+    ) where --- | A self-contained pipeline that is ready to be run-type Pipeline   = Pipe () C+import Control.Monad (forever)+import Control.Proxy.Class (Proxy(request, respond, (>->), (?>=)))+import Control.Proxy.Synonym (Pipe, Consumer, Producer, C)+import Control.Proxy.Trans.Identity (runIdentityP)  {-| Wait for input from upstream -    'await' blocks until input is available -}-await :: (Monad m) => Pipe a b m a+    'await' blocks until input is available from upstream. -}+await :: (Monad m, Proxy p) => Pipe p a b m a await = request ()-{-# INLINE await #-} --- | Convert a pure function into a pipe-pipe :: (Monad m) => (a -> b) -> Pipe a b m r-pipe f = go where-    go = Request () (\a -> Respond (f a) (\() -> go))- {-| Deliver output downstream -    'yield' restores control back downstream and binds the result to 'await'. -}-yield :: (Monad m) => b -> Pipe a b m ()-yield = respond-{-# INLINE yield #-}+    'yield' restores control back downstream and binds its value to 'await'. -}+yield :: (Monad m, Proxy p) => b -> p a' a b' b m ()+yield b = runIdentityP $ do+    respond b+    return () +-- | Convert a pure function into a pipe+pipe :: (Monad m, Proxy p) => (a -> b) -> Pipe p a b m r+pipe f = runIdentityP $ forever $ do+    a <- request ()+    respond (f a)+ infixr 9 <+< infixl 9 >+>  -- | Corresponds to ('<<<')/('.') from @Control.Category@-(<+<) :: (Monad m) => Pipe b c m r -> Pipe a b m r -> Pipe a c m r-p1 <+< p2 = ((\() -> p1) <-< (\() -> p2)) ()+(<+<)+ :: (Monad m, Proxy p) => Pipe p b c m r -> Pipe p a b m r -> Pipe p a c m r+p1 <+< p2 = p2 >+> p1  -- | Corresponds to ('>>>') from @Control.Category@-(>+>) :: (Monad m) => Pipe a b m r -> Pipe b c m r -> Pipe a c m r-(>+>) = flip (<+<)+(>+>)+ :: (Monad m, Proxy p) => Pipe p a b m r -> Pipe p b c m r -> Pipe p a c m r+p1 >+> p2 = ((\() -> p1) >-> (\() -> p2)) ()  -- | Corresponds to 'id' from @Control.Category@-idP :: (Monad m) => Pipe a a m r-idP = go where-    go = Request () (\a -> Respond a (\() -> go))+idP :: (Monad m, Proxy p) => Pipe p a a m r+idP = runIdentityP $ forever $ do+    a <- request ()+    respond a --- | Run the 'Pipe' monad transformer, converting it back to the base monad-runPipe :: (Monad m) => Pipeline m r -> m r-runPipe p' = go p' where-    go p = case p of-        Request _ fa  -> go (fa  ())-        Respond _ fb' -> go (fb' ())-        M         m   -> m >>= go-        Pure      r   -> return r+{-| A self-contained 'Pipeline' that is ready to be run++    'Pipeline's never 'request' nor 'respond'. -}+type Pipeline (p :: * -> * -> * -> * -> (* -> *) -> * -> *) = p C () () C++{- $run+    The "Control.Proxy.Core.Fast" and "Control.Proxy.Core.Correct" modules+    provide their corresponding 'runPipe' functions, specialized to their own+    'Proxy' implementations.++    Each implementation must supply its own 'runPipe' function since it is+    the only non-polymorphic 'Pipe' function and the compiler uses it to+    select which underlying proxy implementation to use. -}++{- $upgrade+    You can upgrade classic 'Pipe' code to work with the proxy ecosystem in+    steps.  Each change enables greater interoperability with proxy utilities+    and transformers and if time permits you should implement the entire upgrade+    for your libraries if you want to take advantage of proxy standard+    libraries.++    First, import "Control.Proxy" and "Control.Proxy.Pipe" instead of+    "Control.Pipe".  Then, add 'ProxyFast' after every 'Pipe', 'Producer', or+    'Consumer' in any type signature.  For example, you would convert this:++> import Control.Pipe+>+> fromList :: (Monad m) => [b] -> Producer b m ()+> fromList xs = mapM_ yield xs++    ... to this:++> import Control.Proxy+> import Control.Proxy.Pipe -- transition import+>+> fromList :: (Monad m) => [b] -> Producer ProxyFast b m ()+> fromList xs = mapM_ yield xs++    The change ensures that all your code now works in the 'ProxyFast' monad,+    which is the faster of the two proxy implementations.++    Second, modify all your 'Pipe's to take an empty '()' as their final+    argument, and translate the following functions:++    * ('<+<') to ('<-<')++    * 'runPipe' to 'runProxy'++    For example, you would convert this:++> import Control.Proxy+> import Control.Proxy.Pipe+>+> fromList :: (Monad m) => [b] -> Producer ProxyFast b m ()+> fromList xs = mapM_ yield xs++    ... to this:++> import Control.Proxy+> import Control.Proxy.Pipe+>+> fromList :: (Monad m) => [b] -> () -> Producer ProxyFast b m ()+> fromList xs () = mapM_ yield xs++    Now when you call these within a @do@ block  you must supplying an+    additional @()@ argument:++> examplePipe () = do+>     a <- request ()+>     fromList [1..a] ()++    This change lets you switch from pipe composition, ('<+<'), to proxy+    composition, ('<-<'), so that you can mix proxy utilities with pipes.++    Third, wrap your pipe's implementation in 'runIdentityP' (which+    "Control.Proxy" exports):++> import Control.Proxy+> import Control.Proxy.Pipe+>+> fromList xs () = runIdentityP $ mapM_ yield xs++    Then replace the 'ProxyFast' in the type signature with a type variable @p@+    constrained by the 'Proxy' type class:++> fromList :: (Monad m, Proxy p) => [b] -> () -> Producer p b m ()++    This change upgrades your 'Pipe' to work natively within proxies and proxy+    transformers, without any manual conversion or lifting.  You can now compose+    or sequence your 'Pipe' within any feature set transparently.++    Finally, replace each 'await' with @request ()@ and each 'yield' with+    'respond'.  Also, replace every 'Pipeline' with 'Session'.  This lets you+    drop the "Control.Proxy.Pipe" import:++> import Control.Proxy+>+> fromList :: (Monad m, Proxy p) => [b] -> () -> Producer p b m ()+> fromList xs () = runIdentityP $ mapM_ respond xs++    Also, I encourage you to continue using the 'Pipe', 'Consumer' and+    'Producer' type synonyms to simplify type signatures.  The following+    examples show how they cleanly mix with proxies and their extensions:++> import Control.Proxy+> import Control.Proxy.Trans.Either as E+> import Control.Proxy.Trans.State+>+> -- A Producer enriched with pipe-local state+> example1 :: (Monad m, Proxy p) => () -> Producer (StateP Int p) Int m r+> example1 () = forever $ do+>     n <- get+>     respond n+>     put (n + 1)+>+> -- A Consumer enriched with error-handling+> example2 :: (Proxy p) => () -> Consumer (EitherP String p) Int IO ()+> example2 () = do+>     n <- request ()+>     if (n == 0)+>         then E.throw "Error: received 0"+>         else lift $ print n++-}
Control/Proxy/Prelude.hs view
@@ -1,6 +1,7 @@ -- | Entry point for the Control.Proxy.Prelude hierarchy  module Control.Proxy.Prelude (+    -- * Modules     -- $modules     module Control.Proxy.Prelude.Base,     module Control.Proxy.Prelude.IO,@@ -17,5 +18,4 @@     "Control.Proxy.Prelude.IO" provides proxies for simple 'IO'.      "Control.Proxy.Prelude.Kleisli" provides convenience functions for working-    with Kleisli arrows.--}+    with Kleisli arrows. -}
Control/Proxy/Prelude/Base.hs view
@@ -2,15 +2,19 @@  module Control.Proxy.Prelude.Base (     -- * Maps-    mapB,     mapD,     mapU,-    mapMB,+    mapB,     mapMD,     mapMU,-    execB,+    mapMB,+    useD,+    useU,+    useB,     execD,     execU,+    execB,+     -- * Filters     takeB,     takeB_,@@ -22,45 +26,94 @@     dropWhileU,     filterD,     filterU,+     -- * Lists     fromListS,     fromListC,+     -- * Enumerations     enumFromS,     enumFromC,     enumFromToS,-    enumFromToC-    ) where+    enumFromToC, -import Control.Monad (replicateM_, void, when, (>=>))-import Control.Monad.Trans.Class (lift)-import Control.Proxy.Class (request, respond, idT)-import Control.Proxy.Core (Proxy(..), Server, Client)-import Control.Proxy.Prelude.Kleisli (foreverK, replicateK)+    -- * Folds+    foldD,+    foldU,+    allD,+    allU,+    allD_,+    allU_,+    anyD,+    anyU,+    anyD_,+    anyU_,+    sumD,+    sumU,+    productD,+    productU,+    lengthD,+    lengthU,+    headD,+    headD_,+    headU,+    headU_,+    lastD,+    lastU,+    toListD,+    toListU,+    foldrD,+    foldrU,+    foldlD',+    foldlU', -{-| @(mapB f g)@ applies @f@ to all values going downstream and @g@ to all-    values going upstream.+    -- * Zips and Merges+    zipD,+    mergeD, -    Mnemonic: map \'@B@\'idirectional+    -- * Closed Adapters+    -- $open+    unitD,+    unitU, -> mapB f1 g1 >-> mapB f2 g2 = mapB (f2 . f1) (g1 . g2)->-> mapB id id = idT--}-mapB :: (Monad m) => (a -> b) -> (b' -> a') -> b' -> Proxy a' a b' b m r-mapB f g = go where-    go b' = Request (g b') (\a -> Respond (f a) go)--- mapB f g = foreverK $ request . g >=> respond . f+    -- * Modules+    -- $modules+    module Control.Monad.Trans.State.Strict,+    module Control.Monad.Trans.Writer.Strict,+    module Data.Monoid+    ) where +import Control.MFunctor (hoist)+import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.Writer.Strict (+    WriterT(runWriterT), execWriterT, runWriter, tell )+import Control.Monad.Trans.State.Strict (+    StateT(runStateT), execStateT, runState, execState, get, put )+import Control.Proxy.Class+import Control.Proxy.Synonym+import Control.Proxy.Trans.Identity (runIdentityP, runIdentityK)+import Data.Monoid (+    Monoid,+    Endo(Endo, appEndo),+    All(All, getAll),+    Any(Any, getAny),+    Sum(Sum, getSum),+    Product(Product, getProduct),+    First(First, getFirst),+    Last(Last, getLast) )+ {-| @(mapD f)@ applies @f@ to all values going \'@D@\'ownstream.  > mapD f1 >-> mapD f2 = mapD (f2 . f1) > > mapD id = idT -}-mapD :: (Monad m) => (a -> b) -> x -> Proxy x a x b m r-mapD f = go where-    go x = Request x (\a -> Respond (f a) go)+mapD :: (Monad m, Proxy p) => (a -> b) -> x -> p x a x b m r+mapD f = runIdentityK go where+    go x = do+        a  <- request x+        x2 <- respond (f a)+        go x2 -- mapD f = foreverK $ request >=> respond . f  {-| @(mapU g)@ applies @g@ to all values going \'@U@\'pstream.@@ -69,26 +122,30 @@ > > mapU id = idT -}-mapU :: (Monad m) => (b' -> a') -> b' -> Proxy a' x b' x m r-mapU g = go where-    go b' = Request (g b') (\x -> Respond x go)+mapU :: (Monad m, Proxy p) => (b' -> a') -> b' -> p a' x b' x m r+mapU g = runIdentityK go where+    go b' = do+        x   <- request (g b')+        b'2 <- respond x+        go b'2 -- mapU g = foreverK $ (request . g) >=> respond -{-| @(mapMB f g)@ applies the monadic function @f@ to all values going-    downstream and the monadic function @g@ to all values going upstream.+{-| @(mapB f g)@ applies @f@ to all values going downstream and @g@ to all+    values going upstream. -> mapMB f1 g1 >-> mapMB f2 g2 = mapMB (f1 >=> f2) (g2 >=> g1)+    Mnemonic: map \'@B@\'idirectional++> mapB f1 g1 >-> mapB f2 g2 = mapB (f2 . f1) (g1 . g2) >-> mapMB return return = idT+> mapB id id = idT -}-mapMB :: (Monad m) => (a -> m b) -> (b' -> m a') -> b' -> Proxy a' a b' b m r-mapMB f g = go where-    go b' =-        M (g b' >>= \a' -> return (-        Request a' (\a ->-        M (f a >>= \b -> return (-        Respond b go )))))--- mapMB f g = foreverK $ lift . g >=> request >=> lift . f >=> respond+mapB :: (Monad m, Proxy p) => (a -> b) -> (b' -> a') -> b' -> p a' a b' b m r+mapB f g = runIdentityK go where+    go b' = do+        a   <- request (g b')+        b'2 <- respond (f a )+        go b'2+-- mapB f g = foreverK $ request . g >=> respond . f  {-| @(mapMD f)@ applies the monadic function @f@ to all values going downstream @@ -96,13 +153,14 @@ > > mapMD return = idT -}-mapMD :: (Monad m) => (a -> m b) -> x -> Proxy x a x b m r-mapMD f = go where-    go x =-        Request x (\a ->-        M (f a >>= \b -> return (-        Respond b go )))--- mapMDf = foreverK $ request >=> lift . f >=> respond+mapMD :: (Monad m, Proxy p) => (a -> m b) -> x -> p x a x b m r+mapMD f = runIdentityK go where+    go x = do+        a  <- request x+        b  <- lift (f a)+        x2 <- respond b+        go x2+-- mapMD f = foreverK $ request >=> lift . f >=> respond  {-| @(mapMU g)@ applies the monadic function @g@ to all values going upstream @@ -110,92 +168,166 @@ > > mapMU return = idT -}-mapMU :: (Monad m) => (b' -> m a') -> b' -> Proxy a' x b' x m r-mapMU g = go where-    go b' =-        M (g b' >>= \a' -> return (-        Request a' (\x ->-        Respond x go )))+mapMU :: (Monad m, Proxy p) => (b' -> m a') -> b' -> p a' x b' x m r+mapMU g = runIdentityK go where+    go b' = do+        a'  <- lift (g b')+        x   <- request a'+        b'2 <- respond x+        go b'2 -- mapMU g = foreverK $ lift . g >=> request >=> respond -{-| @(execB md mu)@ executes @mu@ every time values flow upstream through it,-    and executes @md@ every time values flow downstream through it.+{-| @(mapMB f g)@ applies the monadic function @f@ to all values going+    downstream and the monadic function @g@ to all values going upstream. -> execB md1 mu1 >-> execB md2 mu2 = execB (md1 >> md2) (mu2 >> mu1)+> mapMB f1 g1 >-> mapMB f2 g2 = mapMB (f1 >=> f2) (g2 >=> g1) >-> execB (return ()) = idT+> mapMB return return = idT -}-execB :: (Monad m) => m () -> m () -> a' -> Proxy a' a a' a m r-execB md mu = go where-    go a' =-        M (mu >>= \_ -> return (-        Request a' (\a ->-        M (md >>= \_ -> return (-        Respond a go )))))-{- execB md mu = foreverK $ \a' -> do-    lift mu-    a <- request a'-    lift md-    respond a -}+mapMB+ :: (Monad m, Proxy p) => (a -> m b) -> (b' -> m a') -> b' -> p a' a b' b m r+mapMB f g = runIdentityK go where+    go b' = do+        a'  <- lift (g b')+        a   <- request a'+        b   <- lift (f a )+        b'2 <- respond b+        go b'2+-- mapMB f g = foreverK $ lift . g >=> request >=> lift . f >=> respond -{-| @execD md)@ executes @md@ every time values flow downstream through it.+{-| @(useD f)@ executes the monadic function @f@ on all values flowing+    \'@D@\'ownstream +> useD f1 >-> useD f2 = useD (\a -> f1 a >> f2 a)+>+> useD (\_ -> return ()) = idT+-}+useD :: (Monad m, Proxy p) => (a -> m r1) -> x -> p x a x a m r+useD f = runIdentityK go where+    go x = do+        a  <- request x+        lift $ f a+        x2 <- respond a+        go x2++{-| @(useU g)@ executes the monadic function @g@ on all values flowing+    \'@U@\'pstream++> useU g1 >-> useU g2 = useU (\a' -> g2 a' >> g1 a')+>+> useU (\_ -> return ()) = idT+-}+useU :: (Monad m, Proxy p) => (a' -> m r2) -> a' -> p a' x a' x m r+useU g = runIdentityK go where+    go a' = do+        lift $ g a'+        x   <- request a'+        a'2 <- respond x+        go a'2++{-| @(useB f g)@ executes the monadic function @f@ on all values flowing+    downstream and the monadic function @g@ on all values flowing upstream++> useB f1 g1 >-> useB f2 g2 = useB (\a -> f1 a >> f2 a) (\a' -> g2 a' >> g1 a')+>+> useB (\_ -> return ()) (\_ -> return ()) = idT+-}+useB+ :: (Monad m, Proxy p) => (a -> m r1) -> (a' -> m r2) -> a' -> p a' a a' a m r+useB f g = runIdentityK go where+    go a' = do+        lift $ g a'+        a   <- request a'+        lift $ f a+        a'2 <- respond a+        go a'2++{-| @(execD md)@ executes @md@ every time values flow downstream through it.+ > execD md1 >-> execD md2 = execD (md1 >> md2) > > execD (return ()) = idT -}-execD :: (Monad m) => m () -> a' -> Proxy a' a a' a m r-execD md = go where-    go a' =-        Request a' (\a ->-        M (md >>= \_ -> return (-        Respond a go )))+execD :: (Monad m, Proxy p) => m r1 -> a' -> p a' a a' a m r+execD md = runIdentityK go where+    go a' = do+        a   <- request a'+        lift md+        a'2 <- respond a+        go a'2 {- execD md = foreverK $ \a' -> do     a <- request a'     lift md     respond a -} -{-| @execU mu)@ executes @mu@ every time values flow upstream through it.+{-| @(execU mu)@ executes @mu@ every time values flow upstream through it.  > execU mu1 >-> execU mu2 = execU (mu2 >> mu1) > > execU (return ()) = idT -}-execU :: (Monad m) => m () -> a' -> Proxy a' a a' a m r-execU mu = go where-    go a' =-        M (mu >>= \_ -> return (-        Request a' (\a ->-        Respond a go )))+execU :: (Monad m, Proxy p) => m r2 -> a' -> p a' a a' a m r+execU mu = runIdentityK go where+    go a' = do+        lift mu+        a   <- request a'+        a'2 <- respond a+        go a'2 {- execU mu = foreverK $ \a' -> do     lift mu     a <- request a'     respond a -} +{-| @(execB md mu)@ executes @mu@ every time values flow upstream through it,+    and executes @md@ every time values flow downstream through it.++> execB md1 mu1 >-> execB md2 mu2 = execB (md1 >> md2) (mu2 >> mu1)+>+> execB (return ()) = idT+-}+execB :: (Monad m, Proxy p) => m r1 -> m r2 -> a' -> p a' a a' a m r+execB md mu = runIdentityK go where+    go a' = do+        lift mu+        a   <- request a'+        lift md+        a'2 <- respond a+        go a'2+{- execB md mu = foreverK $ \a' -> do+    lift mu+    a <- request a'+    lift md+    respond a -}+ {-| @(takeB n)@ allows @n@ upstream/downstream roundtrips to pass through  > takeB n1 >=> takeB n2 = takeB (n1 + n2)  -- n1 >= 0 && n2 >= 0 > > takeB 0 = return -}-takeB :: (Monad m) => Int -> a' -> Proxy a' a a' a m a'-takeB n0 = go n0 where+takeB :: (Monad m, Proxy p) => Int -> a' -> p a' a a' a m a'+takeB n0 = runIdentityK (go n0) where     go n-        | n <= 0    = Pure-        | otherwise = \a' -> Request a' (\a -> Respond a (go (n - 1)))+        | n <= 0    = return+        | otherwise = \a' -> do+             a   <- request a'+             a'2 <- respond a+             go (n - 1) a'2 -- takeB n = replicateK n $ request >=> respond  -- | 'takeB_' is 'takeB' with a @()@ return value, convenient for composing-takeB_ :: (Monad m) => Int -> a' -> Proxy a' a a' a m ()-takeB_ n0 = go n0 where+takeB_ :: (Monad m, Proxy p) => Int -> a' -> p a' a a' a m ()+takeB_ n0 = runIdentityK (go n0) where     go n-        | n <= 0    = \_ -> Pure ()-        | otherwise = \a' -> Request a' (\a -> Respond a (go (n - 1)))-    +        | n <= 0    = \_ -> return ()+        | otherwise = \a' -> do+            a   <- request a'+            a'2 <- respond a+            go (n - 1) a'2 -- takeB_ n = fmap void (takeB n) -{-| @takeWhileD p@ allows values to pass downstream so long as they satisfy the-     predicate @p@.+{-| @(takeWhileD p)@ allows values to pass downstream so long as they satisfy+    the predicate @p@.  > -- Using the "All" monoid over functions: > mempty = \_ -> True@@ -205,41 +337,32 @@ > > takeWhileD mempty = idT -}-takeWhileD :: (Monad m) => (a -> Bool) -> a' -> Proxy a' a a' a m ()-takeWhileD p = go where-    go a' =-        Request a' (\a ->-        if (p a)-        then Respond a go-        else Pure () )-{-  go a' = do+takeWhileD :: (Monad m, Proxy p) => (a -> Bool) -> a' -> p a' a a' a m ()+takeWhileD p = runIdentityK go where+    go a' = do         a <- request a'         if (p a)-        then do-            a'2 <- respond a-            go a'2-        else return () -}+            then do+                a'2 <- respond a+                go a'2+            else return () -{-| @takeWhileU p@ allows values to pass upstream so long as they satisfy the+{-| @(takeWhileU p)@ allows values to pass upstream so long as they satisfy the     predicate @p@.  > takeWhileU p1 >-> takeWhileU p2 = takeWhileU (p1 <> p2) > > takeWhileD mempty = idT -}-takeWhileU :: (Monad m) => (a' -> Bool) -> a' -> Proxy a' a a' a m ()-takeWhileU p = go where+takeWhileU :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> p a' a a' a m ()+takeWhileU p = runIdentityK go where     go a' =         if (p a')-        then Request a' (\a -> Respond a go)-        else Pure ()-{-  go a' =-        if (p a')-        then do-            a <- request a'-            a'2 <- respond a-            go a'2-        else return () -}+            then do+                a   <- request a'+                a'2 <- respond a+                go a'2+            else return_P ()  {-| @(dropD n)@ discards @n@ values going downstream @@ -247,11 +370,13 @@ > > dropD 0 = idT -}-dropD :: (Monad m) => Int -> () -> Proxy () a () a m r-dropD n0 = \() -> go n0 where+dropD :: (Monad m, Proxy p) => Int -> () -> Pipe p a a m r+dropD n0 = \() -> runIdentityP (go n0) where     go n         | n <= 0    = idT ()-        | otherwise = Request () (\_ -> go (n - 1))+        | otherwise = do+            request ()+            go (n - 1) {- dropD n () = do     replicateM_ n $ request ()     idT () -}@@ -262,21 +387,15 @@ > > dropU 0 = idT -}-dropU :: (Monad m) => Int -> a' -> Proxy a' () a' () m r-dropU n0-    | n0 <= 0    = idT-    | otherwise = go (n0 - 1) where-        go n-            | n <= 0    = \_ -> Respond () idT-            | otherwise = \_ -> Respond () (go (n - 1))-{- dropU n a'-    | n <= 0    = idT a'-    | otherwise = do-        replicateM_ (n - 1) $ respond ()-        a'2 <- respond ()-        idT a'2 -}+dropU :: (Monad m, Proxy p) => Int -> a' -> CoPipe p a' a' m r+dropU n0 = runIdentityK (go n0) where+    go n+        | n <= 0    = idT+        | otherwise = \_ -> do+            a' <- respond ()+            go (n - 1) a' -{-| @(dropWhileD p)@ discards values going upstream until one violates the+{-| @(dropWhileD p)@ discards values going downstream until one violates the     predicate @p@.  > -- Using the "Any" monoid over functions:@@ -287,33 +406,31 @@ > > dropWhileD mempty = idT -}-dropWhileD :: (Monad m) => (a -> Bool) -> () -> Proxy () a () a m r-dropWhileD p () = go where-    go = Request () (\a -> if (p a) then go else Respond a idT)-{-  go = do+dropWhileD :: (Monad m, Proxy p) => (a -> Bool) -> () -> Pipe p a a m r+dropWhileD p () = runIdentityP go where+    go = do         a <- request ()         if (p a)-        then go-        else do-            respond a-            idT () -}+            then go+            else do+                x <- respond a+                idT x -{-| @(dropWhileU p)@ discards values going downstream until one violates the+{-| @(dropWhileU p)@ discards values going upstream until one violates the     predicate @p@.  > dropWhileU p1 >-> dropWhileU p2 = dropWhileU (p1 <> p2) > > dropWhileU mempty = idT -}-dropWhileU :: (Monad m) => (a' -> Bool) -> a' -> Proxy a' () a' () m r-dropWhileU p = go where-    go a' = if (p a') then Respond () go else idT a'-{-  go a' =+dropWhileU :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> CoPipe p a' a' m r+dropWhileU p = runIdentityK go where+    go a' =         if (p a')-        then do-            a'2 <- respond ()-            go a'2-        else idT a' -}+            then do+                a2 <- respond ()+                go a2+            else idT a'  {-| @(filterD p)@ discards values going downstream if they fail the predicate     @p@@@ -326,13 +443,15 @@ > > filterD mempty = idT -}-filterD :: (Monad m) => (a -> Bool) -> () -> Proxy () a () a m r-filterD p = \() ->  go where-    go = Request () (\a -> if (p a) then Respond a (\_ -> go) else go)-{-  go = do+filterD :: (Monad m, Proxy p) => (a -> Bool) -> () -> Pipe p a a m r+filterD p = \() -> runIdentityP go where+    go = do         a <- request ()-        when (p a) $ respond a-        go -}+        if (p a)+            then do+                respond a+                go+            else go  {-| @(filterU p)@ discards values going upstream if they fail the predicate @p@ @@ -340,65 +459,346 @@ > > filterU mempty = idT -}-filterU :: (Monad m) => (a' -> Bool) -> a' -> Proxy a' () a' () m r-filterU p a'0 = go a'0 where+filterU :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> CoPipe p a' a' m r+filterU p = runIdentityK go where     go a' =         if (p a')-        then Request a' (\_ -> Respond () go)-        else Respond () go-{-  go a' = do-        when (p a') $ request a'-        a'2 <- respond ()-        go a'2 -}+        then do+            request a'+            a'2 <- respond ()+            go a'2+        else do+            a'2 <- respond ()+            go a'2 -{-| Convert a list into a 'Server'+{-| Convert a list into a 'Producer'  > fromListS xs >=> fromListS ys = fromListS (xs ++ ys) > > fromListS [] = return -}-fromListS :: (Monad m) => [a] -> () -> Proxy x' x () a m ()-fromListS xs = \_ -> foldr (\e a -> Respond e (\_ -> a)) (Pure ()) xs-{-# INLINE fromListS #-}+fromListS :: (Monad m, Proxy p) => [b] -> () -> Producer p b m ()+fromListS xs = \_ -> foldr (\e a -> respond e ?>= \_ -> a) (return_P ()) xs -- fromListS xs _ = mapM_ respond xs -{-| Convert a list into a 'Client'+{-| Convert a list into a 'CoProducer'  > fromListC xs >=> fromListC ys = fromListC (xs ++ ys) > > fromListC [] = return -}-fromListC :: (Monad m) => [a] -> () -> Proxy a x () y m ()-fromListC xs = \_ -> foldr (\e a -> Request e (\_ -> a)) (Pure ()) xs-{-# INLINE fromListC #-}+fromListC :: (Monad m, Proxy p) => [a'] -> () -> CoProducer p a' m ()+fromListC xs = \_ -> foldr (\e a -> request e ?>= \_ -> a) (return_P ()) xs -- fromListC xs _ = mapM_ request xs --- | 'Server' version of 'enumFrom'-enumFromS :: (Enum a, Monad m) => a -> y' -> Proxy x' x y' a m r-enumFromS a0 = \_ -> go a0 where-    go a = Respond a (\_ -> go (succ a))-{-  go a = do-        _ <- respond a-        go (succ a) -}+-- | 'Producer' version of 'enumFrom'+enumFromS :: (Enum b, Monad m, Proxy p) => b -> () -> Producer p b m r+enumFromS b0 = \_ -> runIdentityP (go b0) where+    go b = do+        respond b+        go (succ b) --- | 'Client' version of 'enumFrom'-enumFromC :: (Enum a, Monad m) => a -> y' -> Proxy a x y' y m r-enumFromC a0 = \_ -> go a0 where-    go a = Request a (\_ -> go (succ a))-{-  go a = do-        _ <- request a-        go (succ a) -}+-- | 'CoProducer' version of 'enumFrom'+enumFromC :: (Enum a', Monad m, Proxy p) => a' -> () -> CoProducer p a' m r+enumFromC a'0 = \_ -> runIdentityP (go a'0) where+    go a' = do+        request a'+        go (succ a') --- | 'Server' version of 'enumFromTo'-enumFromToS :: (Enum a, Ord a, Monad m) => a -> a -> y' -> Proxy x' x y' a m ()-enumFromToS a1 a2 _ = go a1 where-    go n-        | n > a2    = Pure ()-        | otherwise = Respond n (\_ -> go (succ n))+-- | 'Producer' version of 'enumFromTo'+enumFromToS+ :: (Enum b, Ord b, Monad m, Proxy p) => b -> b -> () -> Producer p b m ()+enumFromToS b1 b2 _ = runIdentityP (go b1) where+    go b+        | b > b2    = return ()+        | otherwise = do+            respond b+            go (succ b) --- | 'Client' version of 'enumFromTo'-enumFromToC :: (Enum a, Ord a, Monad m) => a -> a -> y' -> Proxy a x y' y m ()-enumFromToC a1 a2 _ = go a1 where+-- | 'CoProducer' version of 'enumFromTo'+enumFromToC+ :: (Enum a', Ord a', Monad m, Proxy p)+ => a' -> a' -> () -> CoProducer p a' m ()+enumFromToC a1 a2 _ = runIdentityP (go a1) where     go n-        | n > a2 = Pure ()-        | otherwise = Request n (\_ -> go (succ n))+        | n > a2 = return ()+        | otherwise = do+            request n+            go (succ n)++{-| Fold values flowing \'@D@\'ownstream++> foldD f >-> foldD g = foldD (f <> g)+>+> foldD mempty = idT+-}+foldD+ :: (Monad m, Proxy p, Monoid w) => (a -> w) -> x -> p x a x a (WriterT w m) r+foldD f = runIdentityK go where+    go x = do+        a <- request x+        lift $ tell $ f a+        x2 <- respond a+        go x2++{-| Fold values flowing \'@U@\'pstream++> foldU f >-> foldU g = foldU (g <> f)+>+> foldU mempty = idT+-}+foldU+ :: (Monad m, Proxy p, Monoid w)+ => (a' -> w) -> a' -> p a' x a' x (WriterT w m) r+foldU f = runIdentityK go where+    go a' = do+        lift $ tell $ f a'+        x <- request a'+        a'2 <- respond x+        go a'2++{-| Fold that returns whether 'All' values flowing \'@D@\'ownstream satisfy the+    predicate -}+allD :: (Monad m, Proxy p) => (a -> Bool) -> x -> p x a x a (WriterT All m) r+allD pred = foldD (All . pred)++{-| Fold that returns whether 'All' values flowing \'@U@\'pstream satisfy the+    predicate -}+allU+ :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> p a' x a' x (WriterT All m) r+allU pred = foldU (All . pred)++{-| Fold that returns whether 'All' values flowing \'@D@\'ownstream satisfy the+    predicate++    'allD_' terminates on the first value that fails the predicate -}+allD_ :: (Monad m, Proxy p) => (a -> Bool) -> x -> p x a x a (WriterT All m) ()+allD_ pred = runIdentityK go where+    go x = do+        a <- request x+        if (pred a)+            then do+                x2 <- respond a+                go x2+            else lift $ tell $ All False++{-| Fold that returns whether 'All' values flowing \'@U@\'pstream satisfy the+    predicate++    'allU_' terminates on the first value that fails the predicate -}+allU_+ :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> p a' x a' x (WriterT All m) ()+allU_ pred = runIdentityK go where+    go a' =+        if (pred a')+            then do+                x   <- request a'+                a'2 <- respond x+                go a'2+            else lift $ tell $ All False++{-| Fold that returns whether 'Any' value flowing \'@D@\'ownstream satisfies+    the predicate -}+anyD :: (Monad m, Proxy p) => (a -> Bool) -> x -> p x a x a (WriterT Any m) r+anyD pred = foldD (Any . pred)++{-| Fold that returns whether 'Any' value flowing \'@U@\'pstream satisfies+    the predicate -}+anyU+ :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> p a' x a' x (WriterT Any m) r+anyU pred = foldU (Any . pred)++{-| Fold that returns whether 'Any' value flowing \'@D@\'ownstream satisfies the+    predicate++    'anyD_' terminates on the first value that satisfies the predicate -}+anyD_ :: (Monad m, Proxy p) => (a -> Bool) -> x -> p x a x a (WriterT Any m) ()+anyD_ pred = runIdentityK go where+    go x = do+        a <- request x+        if (pred a)+            then lift $ tell $ Any True+            else do+                x2 <- respond a+                go x2++{-| Fold that returns whether 'Any' value flowing \'@U@\'pstream satisfies the+    predicate++    'anyU_' terminates on the first value that satisfies the predicate -}+anyU_+ :: (Monad m, Proxy p) => (a' -> Bool) -> a' -> p a' x a' x (WriterT Any m) ()+anyU_ pred = runIdentityK go where+    go a' =+        if (pred a')+            then lift $ tell $ Any True+            else do+                x   <- request a'+                a'2 <- respond x+                go a'2++-- | Compute the 'Sum' of all values that flow \'@D@\'ownstream+sumD :: (Monad m, Proxy p, Num a) => x -> p x a x a (WriterT (Sum a) m) r+sumD = foldD Sum++-- | Compute the 'Sum' of all values that flow \'@U@\'pstream+sumU :: (Monad m, Proxy p, Num a') => a' -> p a' x a' x (WriterT (Sum a') m) r+sumU = foldU Sum++-- | Compute the 'Product' of all values that flow \'@D@\'ownstream+productD+ :: (Monad m, Proxy p, Num a) => x -> p x a x a (WriterT (Product a) m) r+productD = foldD Product++-- | Compute the 'Product' of all values that flow \'@U@\'pstream+productU+ :: (Monad m, Proxy p, Num a') => a' -> p a' x a' x (WriterT (Product a') m) r+productU = foldU Product++-- | Count how many values flow \'@D@\'ownstream+lengthD :: (Monad m, Proxy p) => x -> p x a x a (WriterT (Sum Int) m) r+lengthD = foldD (\_ -> Sum 1)++-- | Count how many values flow \'@U@\'pstream+lengthU :: (Monad m, Proxy p) => a' -> p a' x a' x (WriterT (Sum Int) m) r+lengthU = foldU (\_ -> Sum 1)++-- | Retrieve the first value going \'@D@\'ownstream+headD :: (Monad m, Proxy p) => x -> p x a x a (WriterT (First a) m) r+headD = foldD (First . Just)++{-| Retrieve the first value going \'@D@\'ownstream++    'headD_' terminates on the first value it receives -}+headD_ :: (Monad m, Proxy p) => x -> p x a x a (WriterT (First a) m) ()+headD_ x = runIdentityP $ do+    a <- request x+    lift $ tell $ First (Just a)++-- | Retrieve the first value going \'@U@\'pstream+headU :: (Monad m, Proxy p) => a' -> p a' x a' x (WriterT (First a') m) r+headU = foldU (First . Just)++{-| Retrieve the first value going \'@U@\'pstream++    'headU_' terminates on the first value it receives -}+headU_ :: (Monad m, Proxy p) => a' -> p a' x a' x (WriterT (First a') m) ()+headU_ a' = runIdentityP $ lift $ tell $ First (Just a')++-- | Retrieve the last value going \'@D@\'ownstream+lastD :: (Monad m, Proxy p) => x -> p x a x a (WriterT (Last a) m) r+lastD = foldD (Last . Just)++-- | Retrieve the last value going \'@U@\'pstream+lastU :: (Monad m, Proxy p) => a' -> p a' x a' x (WriterT (Last a') m) r+lastU = foldU (Last . Just)++-- | Fold the values flowing \'@D@\'ownstream into a list+toListD :: (Monad m, Proxy p) => x -> p x a x a (WriterT [a] m) r+toListD = foldD (\x -> [x])++-- | Fold the values flowing \'@U@\'pstream into a list+toListU :: (Monad m, Proxy p) => a' -> p a' x a' x (WriterT [a'] m) r+toListU = foldU (\x -> [x])++{-| Fold equivalent to 'foldr'++    To see why, consider this isomorphic type for 'foldr':++> foldr :: (a -> b -> b) -> [a] -> Endo b+-}+foldrD+ :: (Monad m, Proxy p) => (a -> b -> b) -> x -> p x a x a (WriterT (Endo b) m) r+foldrD step = foldD (Endo . step)++-- | Fold equivalent to 'foldr'+foldrU+ :: (Monad m, Proxy p)+ => (a' -> b -> b) -> a' -> p a' x a' x (WriterT (Endo b) m) r+foldrU step = foldU (Endo . step)++-- | Left strict fold over \'@D@\'ownstream values+foldlD'+ :: (Monad m, Proxy p) => (b -> a -> b) -> x -> p x a x a (StateT b m) r+foldlD' f = runIdentityK go where+    go x = do+        a  <- request x+        lift $ do+            b <- get+            put $! f b a+        x2 <- respond a+        go x2++-- | Left strict fold over \'@U@\'pstream values+foldlU'+ :: (Monad m, Proxy p) => (b -> a' -> b) -> a' -> p a' x a' x (StateT b m) r+foldlU' f = runIdentityK go where+    go a' = do+        lift $ do+            b <- get+            put $! f b a'+        x   <- request a'+        a'2 <- respond x+        go a'2++-- | Zip values flowing downstream+zipD+ :: (Monad m, Proxy p1, Proxy p2, Proxy p3)+ => () -> Consumer p1 a (Consumer p2 b (Producer p3 (a, b) m)) r+zipD () = runIdentityP $ hoist (runIdentityP . hoist runIdentityP) go where+    go = do+        a <- request ()+        lift $ do+            b <- request ()+            lift $ respond (a, b)+        go++-- | Interleave values flowing downstream using simple alternation+mergeD+ :: (Monad m, Proxy p1, Proxy p2, Proxy p3)+ => () -> Consumer p1 a (Consumer p2 a (Producer p3 a m)) r+mergeD () = runIdentityP $ hoist (runIdentityP . hoist runIdentityP) go where+    go = do+        a1 <- request ()+        lift $ do+            lift $ respond a1+            a2 <- request ()+            lift $ respond a2+        go++{- $open+    Use the @unit@ functions when you need to embed a proxy with a closed end+    within an open proxy.  For example, the following code will not type-check+    because @fromListS [1..]@  is a 'Producer' and has a closed upstream end,+    which conflicts with the 'request' statement preceding it:++> p () = do+>     request ()+>     fromList [1..] ()++    You fix this by composing 'unitD' upstream of it, which replaces its closed+    upstream end with an open polymorphic end:++> p () = do+>     request ()+>     (fromList [1..] <-< unitD) ()++-}++-- | Compose 'unitD' with a closed upstream end to create a polymorphic end+unitD :: (Monad m, Proxy p) => y' -> p x' x y' () m r+unitD _ = runIdentityP go where+    go = do+        respond ()+        go++-- | Compose 'unitU' with a closed downstream end to create a polymorphic end+unitU :: (Monad m, Proxy p) => y' -> p () x y' y m r+unitU _ = runIdentityP go where+    go = do+        request ()+        go++{- $modules+    These modules help you build, run, and extract folds+-}
Control/Proxy/Prelude/IO.hs view
@@ -3,8 +3,7 @@     Note that 'String's are very inefficient, and I will release future separate     packages with 'ByteString' and 'Text' operations.  I only provide these to     allow users to test simple I/O without requiring additional library-    dependencies.--}+    dependencies. -}  module Control.Proxy.Prelude.IO (     -- * Standard I/O@@ -25,45 +24,46 @@     promptC,     -- * Handle I/O     -- ** Input-    hGetLineD,-    hGetLineU,+    hGetLineS,+    hGetLineC,     -- ** Output     hPrintB,     hPrintD,     hPrintU,     hPutStrLnB,     hPutStrLnD,-    hPutStrLnU+    hPutStrLnU,     ) where  import Control.Monad (forever) import Control.Monad.Trans.Class (lift) import Control.Proxy.Prelude.Kleisli (foreverK)-import Control.Proxy.Core (Proxy, Client, Server)-import Control.Proxy.Class (request, respond)-import System.IO (Handle, hGetLine, hPutStr, hPutStrLn, hPrint, stdin, stdout)+import Control.Proxy.Class (Proxy(request, respond))+import Control.Proxy.Trans.Identity (runIdentityP, runIdentityK)+import Control.Proxy.Synonym (Client, Server, Producer, CoProducer)+import qualified System.IO as IO --- | Get input from 'stdin' one line at a time and send \'@D@\'ownstream-getLineS :: y' -> Proxy x' x y' String IO r-getLineS _ = forever $ do+-- | A 'Producer' that sends lines from 'stdin' downstream+getLineS :: (Proxy p) => () -> Producer p String IO r+getLineS () = runIdentityP $ forever $ do     str <- lift getLine     respond str --- | Get input from 'stdin' one line at a time and send \'@U@\'pstream-getLineC :: y' -> Proxy String x y' y IO r-getLineC _ = forever $ do+-- | A 'CoProducer' that sends lines from 'stdin' upstream+getLineC :: (Proxy p) => () -> CoProducer p String IO r+getLineC () = runIdentityP $ forever $ do     str <- lift getLine     request str  -- | 'read' input from 'stdin' one line at a time and send \'@D@\'ownstream-readLnS :: (Read a) => y' -> Proxy x' x y' a IO r-readLnS _ = forever $ do+readLnS :: (Read b, Proxy p) => () -> Producer p b IO r+readLnS () = runIdentityP $ forever $ do     a <- lift readLn     respond a  -- | 'read' input from 'stdin' one line at a time and send \'@U@\'pstream-readLnC :: (Read a) => y' -> Proxy a x y' y IO r-readLnC _ = forever $ do+readLnC :: (Read a', Proxy p) => () -> CoProducer p a' IO r+readLnC () = runIdentityP $ forever $ do     a <- lift readLn     request a @@ -71,8 +71,8 @@      Prefixes upstream values with \"@U: @\" and downstream values with \"@D: @\" -}-printB :: (Show a, Show a') => a' -> Proxy a' a a' a IO r-printB = foreverK $ \a' -> do+printB :: (Show a', Show a, Proxy p) => a' -> p a' a a' a IO r+printB = runIdentityK $ foreverK $ \a' -> do     lift $ do         putStr "U: "         print a'@@ -83,15 +83,15 @@     respond a  -- | 'print's all values flowing \'@D@\'ownstream to 'stdout'-printD :: (Show a) => x -> Proxy x a x a IO r-printD = foreverK $ \x -> do+printD :: (Show a, Proxy p) => x -> p x a x a IO r+printD = runIdentityK $ foreverK $ \x -> do     a <- request x     lift $ print a     respond a  -- | 'print's all values flowing \'@U@\'pstream to 'stdout'-printU :: (Show a') => a' -> Proxy a' x a' x IO r-printU = foreverK $ \a' -> do+printU :: (Show a', Proxy p) => a' -> p a' x a' x IO r+printU = runIdentityK $ foreverK $ \a' -> do     lift $ print a'     x <- request a'     respond x@@ -100,8 +100,8 @@      Prefixes upstream values with \"@U: @\" and downstream values with \"@D: @\" -}-putStrLnB :: String -> Proxy String String String String IO r-putStrLnB = foreverK $ \a' -> do+putStrLnB :: (Proxy p) => String -> p String String String String IO r+putStrLnB = runIdentityK $ foreverK $ \a' -> do     lift $ do         putStr "U: "         putStrLn a'@@ -112,72 +112,84 @@     respond a  -- | 'putStrLn's all values flowing \'@D@\'ownstream to 'stdout'-putStrLnD :: x -> Proxy x String x String IO r-putStrLnD = foreverK $ \x -> do+putStrLnD :: (Proxy p) => x -> p x String x String IO r+putStrLnD = runIdentityK $ foreverK $ \x -> do     a <- request x     lift $ putStrLn a     respond a  -- | 'putStrLn's all values flowing \'@U@\'pstream to 'stdout'-putStrLnU :: String -> Proxy String x String x IO r-putStrLnU = foreverK $ \a' -> do+putStrLnU :: (Proxy p) => String -> p String x String x IO r+putStrLnU = runIdentityK $ foreverK $ \a' -> do     lift $ putStrLn a'     x <- request a'     respond x  -- | Convert 'stdin'/'stdout' into a line-based 'Server'-promptS :: String -> Proxy x' x String String IO r-promptS = foreverK $ \send -> do+promptS :: (Proxy p) => String -> Server p String String IO r+promptS = runIdentityK $ foreverK $ \send -> do     recv <- lift $ do         putStrLn send         getLine     respond recv  -- | Convert 'stdin'/'stdout' into a line-based 'Client'-promptC :: y' -> Proxy String String y' y IO r-promptC _ = forever $ do+promptC :: (Proxy p) => () -> Client p String String IO r+promptC () = runIdentityP $ forever $ do     send <- lift getLine     recv <- request send     lift $ putStrLn recv --- | Get input from a handle one line at a time and send \'@D@\'ownstream-hGetLineD :: Handle -> y' -> Proxy x' x y' String IO r-hGetLineD h _ = forever $ do-    str <- lift $ hGetLine h-    respond str+-- | A 'Producer' that sends lines from a handle downstream+hGetLineS :: (Proxy p) => IO.Handle -> () -> Producer p String IO ()+hGetLineS h () = runIdentityP go where+    go = do+        eof <- lift $ IO.hIsEOF h+        if eof+            then return ()+            else do+                str <- lift $ IO.hGetLine h+                respond str+                go --- | Get input from a handle one line at a time and send \'@U@\'pstream-hGetLineU :: Handle -> y' -> Proxy String x y' y IO r-hGetLineU h _ = forever $ do-    str <- lift $ hGetLine h-    request str+-- | A 'CoProducer' that sends lines from a 'Handle' upstream+hGetLineC :: (Proxy p) => IO.Handle -> () -> CoProducer p String IO ()+hGetLineC h () = runIdentityP go where+    go = do+        eof <- lift $ IO.hIsEOF h+        if eof+            then return ()+            else do+                str <- lift $ IO.hGetLine h+                request str+                go  {-| 'print's all values flowing through it to a 'Handle'      Prefixes upstream values with \"@U: @\" and downstream values with \"@D: @\" -}-hPrintB :: (Show a, Show a') => Handle -> a' -> Proxy a' a a' a IO r-hPrintB h = foreverK $ \a' -> do+hPrintB :: (Show a, Show a', Proxy p) => IO.Handle -> a' -> p a' a a' a IO r+hPrintB h = runIdentityK $ foreverK $ \a' -> do     lift $ do-        hPutStr h "U: "-        hPrint h a'+        IO.hPutStr h "U: "+        IO.hPrint h a'     a <- request a'     lift $ do-        hPutStr h "D: "-        hPrint h a+        IO.hPutStr h "D: "+        IO.hPrint h a     respond a  -- | 'print's all values flowing \'@D@\'ownstream to a 'Handle'-hPrintD :: (Show a) => Handle -> x -> Proxy x a x a IO r-hPrintD h = foreverK $ \x -> do+hPrintD :: (Show a, Proxy p) => IO.Handle -> x -> p x a x a IO r+hPrintD h = runIdentityK $ foreverK $ \x -> do     a <- request x-    lift $ hPrint h a+    lift $ IO.hPrint h a     respond a  -- | 'print's all values flowing \'@U@\'pstream to a 'Handle'-hPrintU :: (Show a') => Handle -> a' -> Proxy a' x a' x IO r-hPrintU h = foreverK $ \a' -> do-    lift $ hPrint h a'+hPrintU :: (Show a', Proxy p) => IO.Handle -> a' -> p a' x a' x IO r+hPrintU h = runIdentityK $ foreverK $ \a' -> do+    lift $ IO.hPrint h a'     x <- request a'     respond x @@ -185,27 +197,28 @@      Prefixes upstream values with \"@U: @\" and downstream values with \"@D: @\" -}-hPutStrLnB :: Handle -> String -> Proxy String String String String IO r-hPutStrLnB h = foreverK $ \a' -> do+hPutStrLnB+ :: (Proxy p) => IO.Handle -> String -> p String String String String IO r+hPutStrLnB h = runIdentityK $ foreverK $ \a' -> do     lift $ do-        hPutStr h "U: "-        hPutStrLn h a'+        IO.hPutStr h "U: "+        IO.hPutStrLn h a'     a <- request a'     lift $ do-        hPutStr h "D: "-        hPutStrLn h a+        IO.hPutStr h "D: "+        IO.hPutStrLn h a     respond a  -- | 'putStrLn's all values flowing \'@D@\'ownstream to a 'Handle'-hPutStrLnD :: Handle -> x -> Proxy x String x String IO r-hPutStrLnD h = foreverK $ \x -> do+hPutStrLnD :: (Proxy p) => IO.Handle -> x -> p x String x String IO r+hPutStrLnD h = runIdentityK $ foreverK $ \x -> do     a <- request x-    lift $ hPutStrLn h a+    lift $ IO.hPutStrLn h a     respond a  -- | 'putStrLn's all values flowing \'@U@\'pstream to a 'Handle'-hPutStrLnU :: Handle -> String -> Proxy String x String x IO r-hPutStrLnU h = foreverK $ \a' -> do-    lift $ hPutStrLn h a'+hPutStrLnU :: (Proxy p) => IO.Handle -> String -> p String x String x IO r+hPutStrLnU h = runIdentityK $ foreverK $ \a' -> do+    lift $ IO.hPutStrLn h a'     x <- request a'     respond x
Control/Proxy/Prelude/Kleisli.hs view
@@ -1,36 +1,36 @@+{-# LANGUAGE Rank2Types #-}+ -- | Utility functions for Kleisli arrows  module Control.Proxy.Prelude.Kleisli (     -- * Core utility functions-    -- $utility     foreverK,     replicateK,-    mapK+    liftK,+    hoistK,+    raiseK,     ) where -import Control.Monad (forever, (>=>))+import Control.MFunctor (MFunctor(hoist)) import Control.Monad.Trans.Class (MonadTrans(lift))-import Control.Proxy.Class (Interact(request, respond))-import Data.Closed (C) -{- $utility-    Use 'foreverK' to abstract away the following common pattern:+{-| Compose a \'@K@\'leisli arrow with itself forever +    Use 'foreverK' to abstract away the following common recursion pattern:+ > p a = do >     ... >     a' <- respond b >     p a' -    Using 'foreverK', you can avoid the manual recursion:+    Using 'foreverK', you can instead write:  > p = foreverK $ \a -> do >     ... >     respond b -}---- | Compose a \'@K@\'leisli arrow with itself forever foreverK :: (Monad m) => (a -> m a) -> (a -> m b)-foreverK k = let r = k >=> r in r+foreverK k = let r = \a -> k a >>= r in r {- foreverK uses 'let' to avoid a space leak.    See: http://hackage.haskell.org/trac/ghc/ticket/5205 -} @@ -40,14 +40,48 @@     go n         | n < 1     = return         | n == 1    = k-        | otherwise = k >=> go (n - 1)+        | otherwise = \a -> k a >>= go (n - 1)  {-| Convenience function equivalent to @(lift .)@ -> mapK f >=> mapK g = mapK (f >=> g)+> liftK f >=> liftK g = liftK (f >=> g) >-> mapK return = return+> liftK return = return -}-mapK :: (Monad m, MonadTrans t) => (a -> m b) -> (a -> t m b)-mapK = (lift .)-{-# INLINABLE mapK #-}+liftK :: (Monad m, MonadTrans t) => (a -> m b) -> (a -> t m b)+liftK k a = lift (k a)+-- liftK = (lift .)++{-| Convenience function equivalent to @(hoist f .)@++> hoistK f p1 >-> hoistK f p2 = hoistK f (p1 >-> p2)+>+> hoistK f idT = idT++> hoistK f p1 >=> hoistK f p2 = hoistK f (p1 >=> p2)+>+> hoistK f return = return++> hoistK f . hoistK g = hoistK (f . g)+>+> hoistK id = id+-}+hoistK+ :: (Monad m, MFunctor t)+ => (forall a . m a -> n a) -> ((b' -> t m b) -> (b' -> t n b))+hoistK k p a' = hoist k (p a')+-- hoistK k = (hoist k .)++{-| Convenience function equivalent to @(hoist lift .)@++> raiseK p1 >-> raiseK p2 = raiseK (p1 >-> p2)+>+> raiseK idT = idT++> raiseK p1 >=> raiseK p2 = raiseK (p1 >=> p2)+>+> raiseK return = return+-}+raiseK+ :: (Monad m, MFunctor t1, MonadTrans t2) => (q -> t1 m r) -> (q -> t1 (t2 m) r)+raiseK = (hoist lift .)
+ Control/Proxy/Synonym.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE KindSignatures #-}++{-| These type synonyms simplify type signatures when proxies do not use all+    their type variables. -}++module Control.Proxy.Synonym (+    -- * Synonyms+    Pipe,+    Producer,+    Consumer,+    CoPipe,+    CoProducer,+    CoConsumer,+    Client,+    Server,+    Session,++    -- * Closed+    C+    ) where++-- | A unidirectional 'Proxy'.+type Pipe (p :: * -> * -> * -> * -> (* -> *) -> * -> *) a b = p () a () b++{-| A 'Pipe' that produces values++    'Producer's never 'request'. -}+type Producer (p :: * -> * -> * -> * -> (* -> *) -> * -> *) b = p C () () b++{-| A 'Pipe' that consumes values++    'Consumer's never 'respond'. -}+type Consumer (p :: * -> * -> * -> * -> (* -> *) -> * -> *) a = p () a () C++-- | A 'Pipe' where everything flows upstream+type CoPipe (p :: * -> * -> * -> * -> (* -> *) -> * -> *) a' b' = p a' () b' ()++{-| A 'CoPipe' that produces values flowing upstream++    'CoProducer's never 'respond'. -}+type CoProducer (p :: * -> * -> * -> * -> (* -> *) -> * -> *) a' = p a' () () C++{-| A 'CoConsumer' that consumes values flowing upstream++    'CoConsumer's never 'request'. -}+type CoConsumer (p :: * -> * -> * -> * -> (* -> *) -> * -> *) b' = p C () b' ()++{-| @Server b' b@ receives requests of type @b'@ and sends responses of type+    @b@.++    'Server's never 'request'. -}+type Server (p :: * -> * -> * -> * -> (* -> *) -> * -> *) b' b = p C () b' b++{-| @Client a' a@ sends requests of type @a'@ and receives responses of+    type @a@.++    'Client's never 'respond'. -}+type Client (p :: * -> * -> * -> * -> (* -> *) -> * -> *) a' a = p a' a () C++{-| A self-contained 'Session', ready to be run by 'runSession'++    'Session's never 'request' or 'respond'. -}+type Session (p :: * -> * -> * -> * -> (* -> *) -> * -> *) = p C () () C++-- | The empty type, denoting a \'@C@\'losed end+data C = C -- Constructor not exported, but I include it to avoid EmptyDataDecls
Control/Proxy/Trans.hs view
@@ -1,38 +1,71 @@-{-| You can define your own extensions to the 'Proxy' type by writing your own-    \"proxy transformers\".  Proxy transformers are monad transformers that-    correctly lift 'Proxy' composition from the base monad.  Stack multiple-    proxy transformers to chain features together. -}+{-| You can define your own proxy extensions by writing your own \"proxy+    transformers\".  Proxy transformers are monad transformers that also+    correctly lift all proxy operations from the base proxy type to the+    extended proxy type.  Stack multiple proxy transformers to chain features+    together.+-}      module Control.Proxy.Trans (     -- * Proxy Transformers-    ProxyTrans(..)-    )where+    ProxyTrans(..),+    mapP +    -- * Laws+    -- $laws+    ) where+ import Control.Proxy.Class -{-| 'mapP' defines a functor that preserves 'Proxy' composition and Kleisli-    composition.+-- | Uniform interface to lifting proxies+class ProxyTrans t where+    liftP :: (Monad m, Proxy p) => p a' a b' b m r -> t p a' a b' b m r +{-| Lift a 'Proxy' Kleisli arrow++> mapP = (lift .)+-}+mapP :: (Monad m, Proxy p, ProxyTrans t)+     => (q -> p a' a b' b m r) -> (q -> t p a' a b' b m r)+mapP = (liftP .)++{- $laws+     'mapP' defines a functor that preserves five categories:++    * Kleisli category++    * The two Proxy categories++    * \"request\" category++    * \"respond\" category+     Laws:      * Functor between 'Proxy' categories -> mapP (f <-< g) = mapP f <-< mapP g+> mapP (f >-> g) = mapP f >-> mapP g+> > mapP idT = idT +> mapP (f >~> g) = mapP f >~> mapP g+>+> mapP idPush = idPush+     * Functor between Kleisli categories  > mapP (f <=< g) = mapP f <=< mapP g+> > mapP return = return -    Minimal complete definition: 'mapP' or 'liftP'.  Defining 'liftP' is more-    efficient.--}-class ProxyTrans t where-    liftP :: (Monad (p b c d e m), Channel p)-          => p b c d e m r -> t p b c d e m r-    liftP f = mapP (\() -> f) ()+    * Functor between \"request\" categories -    mapP :: (Monad (p b c d e m), Channel p)-         => (a -> p b c d e m r) -> (a -> t p b c d e m r)-    mapP = (liftP .)+> mapP (f /</ g) = mapP f /</ mapP g -- when /</ is defined+>+> mapP request = request++    * Functor between \"respond\" categories++> mapP (f \<\ g) = mapP f \<\ mapP g -- when \<\ is defined+>+> mapP respond = respond+-}
Control/Proxy/Trans/Either.hs view
@@ -1,6 +1,6 @@ -- | This module provides the proxy transformer equivalent of 'EitherT'. -{-# LANGUAGE FlexibleContexts, KindSignatures #-}+{-# LANGUAGE KindSignatures #-}  module Control.Proxy.Trans.Either (     -- * EitherP@@ -17,11 +17,12 @@     ) where  import Control.Applicative (Applicative(pure, (<*>)), Alternative(empty, (<|>)))-import Control.Monad (liftM, ap, MonadPlus(mzero, mplus))+import Control.Monad (MonadPlus(mzero, mplus)) import Control.Monad.IO.Class (MonadIO(liftIO)) import Control.Monad.Trans.Class (MonadTrans(lift))-import Control.MFunctor (MFunctor(mapT))-import Control.Proxy.Class (Channel(idT, (>->))) +import Control.MFunctor (MFunctor(hoist))+import Control.PFunctor (PFunctor(hoistP))+import Control.Proxy.Class import Control.Proxy.Trans (ProxyTrans(liftP)) import Prelude hiding (catch) @@ -29,59 +30,114 @@ newtype EitherP e p a' a b' b (m :: * -> *) r   = EitherP { runEitherP :: p a' a b' b m (Either e r) } -instance (Monad (p a' a b' b m)) => Functor (EitherP e p a' a b' b m) where-    fmap = liftM+instance (Proxy              p, Monad m)+       => Functor (EitherP e p a' a b' b m) where+    fmap f p = EitherP (+        runEitherP p ?>= \e ->+        return_P (case e of+            Left  l -> Left l+            Right r -> Right (f r) ) )+ -- fmap f = EitherP . liftM (fmap f) . runEitherP -instance (Monad (p a' a b' b m)) => Applicative (EitherP e p a' a b' b m) where-    pure  = return-    (<*>) = ap+instance (Proxy                  p, Monad m)+       => Applicative (EitherP e p a' a b' b m) where+    pure = return+    fp <*> xp = EitherP (+        runEitherP fp ?>= \e1 ->+        case e1 of+            Left  l -> return_P (Left l)+            Right f ->+                 runEitherP xp ?>= \e2 ->+                 return_P (case e2 of+                      Left l  -> Left  l+                      Right x -> Right (f x) ) )+ -- fp <*> xp = EitherP ((<*>) <$> (runEitherP fp) <*> (runEitherP xp)) -instance (Monad (p a' a b' b m)) => Monad (EitherP e p a' a b' b m) where-    return = right-    m >>= f = EitherP $ do-        e <- runEitherP m-        runEitherP $ case e of-            Left  l -> left l-            Right r -> f    r+instance (Proxy            p, Monad m)+       => Monad (EitherP e p a' a b' b m) where+    return = return_P+    (>>=) = (?>=) -instance (MonadPlus (p a' a b' b m))- => Alternative (EitherP e p a' a b' b m) where+instance (MonadPlusP             p, Monad m)+       => Alternative (EitherP e p a' a b' b m) where     empty = mzero     (<|>) = mplus -instance (MonadPlus (p a' a b' b m))- => MonadPlus (EitherP e p a' a b' b m) where-    mzero = EitherP mzero-    mplus m1 m2 = EitherP $ mplus (runEitherP m1) (runEitherP m2)+instance (MonadPlusP            p )+       => MonadPlusP (EitherP e p) where+    mzero_P = EitherP mzero_P+    mplus_P m1 m2 = EitherP (mplus_P (runEitherP m1) (runEitherP m2)) -instance (MonadTrans (p a' a b' b)) => MonadTrans (EitherP e p a' a b' b) where-    lift = EitherP . lift . liftM Right+instance (MonadPlusP           p, Monad m)+       => MonadPlus (EitherP e p a' a b' b m) where+    mzero = mzero_P+    mplus = mplus_P -instance (MonadIO (p a' a b' b m)) => MonadIO (EitherP e p a' a b' b m) where-    liftIO = EitherP . liftIO . liftM Right+instance (Proxy                 p )+       => MonadTrans (EitherP e p a' a b' b) where+    lift = lift_P -instance (MFunctor (p a' a b' b)) => MFunctor (EitherP e p a' a b' b) where-    mapT nat = EitherP . mapT nat . runEitherP+instance (MonadIOP            p )+       => MonadIOP (EitherP e p) where+    liftIO_P m = EitherP (liftIO_P (m >>= \x -> return (Right x)))+ -- liftIO = EitherP . liftIO . liftM Right -instance (Channel p) => Channel (EitherP e p) where-    idT = EitherP . idT-    p1 >-> p2 = (EitherP .) $ runEitherP . p1 >-> runEitherP . p2+instance (MonadIOP           p, MonadIO m)+       => MonadIO (EitherP e p a' a b' b m) where+    liftIO = liftIO_P +instance (Proxy               p )+       => MFunctor (EitherP e p a' a b' b) where+    hoist = hoist_P++instance (Proxy            p )+       => Proxy (EitherP e p) where+    p1 >-> p2 = \c'1 -> EitherP (+        ((\b' -> runEitherP (p1 b')) >-> (\c'2 -> runEitherP (p2 c'2))) c'1 )+ -- p1 >-> p2 = (EitherP .) $ runEitherP . p1 >-> runEitherP . p2++    p1 >~> p2 = \c'1 -> EitherP (+        ((\b' -> runEitherP (p1 b')) >~> (\c'2 -> runEitherP (p2 c'2))) c'1 )+ -- p1 >~> p2 = (EitherP .) $ runEitherP . p1 >~> runEitherP . p2++    request = \a' -> EitherP (request a' ?>= \a  -> return_P (Right a ))+    respond = \b  -> EitherP (respond b  ?>= \b' -> return_P (Right b'))++    return_P = right+    m ?>= f = EitherP (+        runEitherP m ?>= \e ->+        runEitherP (case e of+            Left  l -> left l+            Right r -> f    r ) )++    lift_P m = EitherP (lift_P (m >>= \x -> return (Right x)))+ -- lift = EitherP . lift . liftM Right++    hoist_P nat p = EitherP (hoist_P nat (runEitherP p))+ -- hoist nat = EitherP . hoist nat . runEitherP+ instance ProxyTrans (EitherP e) where-    liftP = EitherP . liftM Right+    liftP p = EitherP (p ?>= \x -> return_P (Right x))+ -- liftP = EitherP . liftM Right +instance PFunctor (EitherP e) where+    hoistP nat = EitherP . nat . runEitherP+ -- | Run an 'EitherP' \'@K@\'leisi arrow, returning either a 'Left' or 'Right' runEitherK  :: (q -> EitherP e p a' a b' b m r) -> (q -> p a' a b' b m (Either e r))-runEitherK = (runEitherP .)+runEitherK p q = runEitherP (p q)+-- runEitherK = (runEitherP .)  -- | Abort the computation and return a 'Left' result-left :: (Monad (p a' a b' b m)) => e -> EitherP e p a' a b' b m r-left = EitherP . return . Left+left :: (Monad m, Proxy p) => e -> EitherP e p a' a b' b m r+left e = EitherP (return_P (Left e))+-- left = EitherP . return . Left  -- | Synonym for 'return'-right :: (Monad (p a' a b' b m)) => r -> EitherP e p a' a b' b m r-right = EitherP . return . Right+right :: (Monad m, Proxy p) => r -> EitherP e p a' a b' b m r+right r = EitherP (return_P (Right r))+-- right = EitherP . return . Right  {- $symmetry     'EitherP' forms a second symmetric monad over the left type variable.@@ -100,29 +156,26 @@ -}  -- | Synonym for 'left'-throw :: (Monad (p a' a b' b m)) => e -> EitherP e p a' a b' b m r+throw :: (Monad m, Proxy p) => e -> EitherP e p a' a b' b m r throw = left  -- | Resume from an aborted operation catch- :: (Monad (p a' a b' b m))+ :: (Monad m, Proxy p)  => EitherP e p a' a b' b m r        -- ^ Original computation  -> (e -> EitherP f p a' a b' b m r) -- ^ Handler  -> EitherP f p a' a b' b m r        -- ^ Handled computation-catch m f = EitherP $ do-    e <- runEitherP m-    runEitherP $ case e of+catch m f = EitherP (+    runEitherP m ?>= \e ->+    runEitherP (case e of         Left  l -> f     l-        Right r -> right r+        Right r -> right r ))  -- | 'catch' with the arguments flipped handle- :: (Monad (p a' a b' b m))+ :: (Monad m, Proxy p)  => (e -> EitherP f p a' a b' b m r) -- ^ Handler  -> EitherP e p a' a b' b m r        -- ^ Original computation  -> EitherP f p a' a b' b m r        -- ^ Handled computation-handle f m = EitherP $ do-    e <- runEitherP m-    runEitherP $ case e of-        Left  l -> f     l-        Right r -> right r+handle f m = catch m f+-- handle = flip catch
Control/Proxy/Trans/Identity.hs view
@@ -1,70 +1,136 @@ -- | This module provides the proxy transformer equivalent of 'IdentityT'. -{-# LANGUAGE FlexibleContexts, KindSignatures #-}+{-# LANGUAGE KindSignatures #-}  module Control.Proxy.Trans.Identity (-    -- * IdentityP+    -- * Identity Proxy Transformer     IdentityP(..),+    identityK,     runIdentityK     ) where  import Control.Applicative (Applicative(pure, (<*>)), Alternative(empty, (<|>)))-import Control.Monad (liftM, ap, MonadPlus(mzero, mplus))+import Control.Monad (MonadPlus(mzero, mplus)) import Control.Monad.IO.Class (MonadIO(liftIO)) import Control.Monad.Trans.Class (MonadTrans(lift))-import Control.MFunctor (MFunctor(mapT))-import Control.Proxy.Class (-    Channel(idT    , (>->)), -    Interact(request, (\>\), respond, (/>/)) )+import Control.MFunctor (MFunctor(hoist))+import Control.PFunctor (PFunctor(hoistP))+import Control.Proxy.Class import Control.Proxy.Trans (ProxyTrans(liftP))  -- | The 'Identity' proxy transformer-newtype IdentityP p a' a b' b (m :: * -> *) r-  = IdentityP { runIdentityP :: p a' a b' b m r }+newtype IdentityP p a' a b' b (m :: * -> *) r =+    IdentityP { runIdentityP :: p a' a b' b m r } -instance (Monad (p a' a b' b m)) => Functor (IdentityP p a' a b' b m) where-    fmap = liftM+instance (Proxy              p, Monad m)+       => Functor (IdentityP p a' a b' b m) where+    fmap f p = IdentityP (+        runIdentityP p ?>= \x ->+        return_P (f x) )+ -- fmap = liftM -instance (Monad (p a' a b' b m)) => Applicative (IdentityP p a' a b' b m) where-    pure  = return-    (<*>) = ap+instance (Proxy                  p, Monad m)+       => Applicative (IdentityP p a' a b' b m) where+    pure = return -instance (Monad (p a' a b' b m)) => Monad (IdentityP p a' a b' b m) where-    return = IdentityP . return-    m >>= f = IdentityP $ runIdentityP m >>= runIdentityP . f+    fp <*> xp = IdentityP (+        runIdentityP fp ?>= \f ->+        runIdentityP xp ?>= \x ->+        return_P (f x) )+ -- fp <*> xp = ap -instance (MonadPlus (p a' a b' b m))- => Alternative (IdentityP p a' a b' b m) where+instance (Proxy            p, Monad m)+       => Monad (IdentityP p a' a b' b m) where+    return = return_P+    (>>=) = (?>=)++instance (MonadPlusP             p, Monad m)+       => Alternative (IdentityP p a' a b' b m) where     empty = mzero     (<|>) = mplus -instance (MonadPlus (p a' a b' b m))- => MonadPlus (IdentityP p a' a b' b m) where-    mzero = IdentityP mzero-    mplus m1 m2 = IdentityP $ mplus (runIdentityP m1) (runIdentityP m2)+instance (MonadPlusP            p )+       => MonadPlusP (IdentityP p) where+    mzero_P = IdentityP mzero_P+    mplus_P m1 m2 = IdentityP (mplus_P (runIdentityP m1) (runIdentityP m2)) -instance (MonadTrans (p a' a b' b)) => MonadTrans (IdentityP p a' a b' b) where-    lift = IdentityP . lift+instance (MonadPlusP           p, Monad m)+       => MonadPlus (IdentityP p a' a b' b m) where+    mzero = mzero_P+    mplus = mplus_P -instance (MonadIO (p a' a b' b m)) => MonadIO (IdentityP p a' a b' b m) where-    liftIO = IdentityP . liftIO+instance (Proxy                 p )+       => MonadTrans (IdentityP p a' a b' b) where+    lift = lift_P -instance (MFunctor (p a' a b' b)) => MFunctor (IdentityP p a' a b' b) where-    mapT nat = IdentityP . mapT nat . runIdentityP+instance (MonadIOP            p )+       => MonadIOP (IdentityP p) where+    liftIO_P m = IdentityP (liftIO_P m)+ -- liftIO = IdentityP . liftIO -instance (Channel p) => Channel (IdentityP p) where-    idT = IdentityP . idT-    p1 >-> p2 = (IdentityP .) $ runIdentityP . p1 >-> runIdentityP . p2+instance (MonadIOP           p, MonadIO m)+       => MonadIO (IdentityP p a' a b' b m) where+    liftIO = liftIO_P -instance (Interact p) => Interact (IdentityP p) where-    request = IdentityP . request-    p1 \>\ p2 = (IdentityP .) $ runIdentityP . p1 \>\ runIdentityP . p2-    respond = IdentityP . respond-    p1 />/ p2 = (IdentityP .) $ runIdentityP . p1 />/ runIdentityP . p2+instance (Proxy               p )+       => MFunctor (IdentityP p a' a b' b) where+    hoist = hoist_P +instance (Proxy            p )+       => Proxy (IdentityP p) where+    p1 >-> p2 = \c'1 -> IdentityP (+        ((\c'2 -> runIdentityP (p1 c'2))+     >-> (\b'  -> runIdentityP (p2 b' )) ) c'1 )+ -- p1 >-> p2 = (IdentityP .) $ runIdentityP . p1 >-> runIdentityP . p2++    p1 >~> p2 = \c'1 -> IdentityP (+        ((\c'2 -> runIdentityP (p1 c'2))+     >~> (\b'  -> runIdentityP (p2 b' )) ) c'1 )+ -- p1 >~> p2 = (IdentityP .) $ runIdentityP . p1 >~> runIdentityP . p2++    request = \a' -> IdentityP (request a')+ -- request = P . request++    respond = \b -> IdentityP (respond b)+ -- respond = P . respond++    return_P = \r -> IdentityP (return_P r)+ -- return = P . return++    m ?>= f = IdentityP (+        runIdentityP m ?>= \x ->+        runIdentityP (f x) )++    lift_P m = IdentityP (lift_P m)+ -- lift = P . lift++    hoist_P nat p = IdentityP (hoist_P nat (runIdentityP p))+ -- hoist nat = IdentityP . hoist nat . runIdentityP++instance (Interact            p )+      =>  Interact (IdentityP p) where+    p1 \>\ p2 = \c'1 -> IdentityP (+        ((\b'  -> runIdentityP (p1 b' ))+     \>\ (\c'2 -> runIdentityP (p2 c'2)) ) c'1 )+ -- p1 \>\ p2 = (IdentityP .) $ runIdentityP . p1 \>\ runIdentityP . p2++    p1 />/ p2 = \a1 -> IdentityP (+        ((\a2 -> runIdentityP (p1 a2))+     />/ (\b  -> runIdentityP (p2 b )) ) a1 )+ -- p1 />/ p2 = (IdentityP .) $ runIdentityP . p1 />/ runIdentityP . p2+ instance ProxyTrans IdentityP where     liftP = IdentityP --- | Run an 'IdentityP' \'@K@\'leisli arrow+instance PFunctor IdentityP where+    hoistP nat = IdentityP . nat . runIdentityP++-- | Wrap a \'@K@\'leisli arrow in 'IdentityP'+identityK :: (q -> p a' a b' b m r) -> (q -> IdentityP p a' a b' b m r)+identityK k q = IdentityP (k q)+-- identityK = (IdentityP .)++-- | Run an 'P' \'@K@\'leisli arrow runIdentityK :: (q -> IdentityP p a' a b' b m r) -> (q -> p a' a b' b m r)-runIdentityK = (runIdentityP .)+runIdentityK k q = runIdentityP (k q)+-- runIdentityK = (runIdentityP .)
Control/Proxy/Trans/Maybe.hs view
@@ -1,6 +1,6 @@ -- | This module provides the proxy transformer equivalent of 'MaybeT'. -{-# LANGUAGE FlexibleContexts, KindSignatures #-}+{-# LANGUAGE KindSignatures #-}  module Control.Proxy.Trans.Maybe (     -- * MaybeP@@ -12,68 +12,125 @@     ) where  import Control.Applicative (Applicative(pure, (<*>)), Alternative(empty, (<|>)))-import Control.Monad (liftM, ap, MonadPlus(mzero, mplus))+import Control.Monad (MonadPlus(mzero, mplus)) import Control.Monad.IO.Class (MonadIO(liftIO)) import Control.Monad.Trans.Class (MonadTrans(lift))-import Control.MFunctor (MFunctor(mapT))-import Control.Proxy.Class (Channel(idT, (>->)))+import Control.MFunctor (MFunctor(hoist))+import Control.PFunctor (PFunctor(hoistP))+import Control.Proxy.Class import Control.Proxy.Trans (ProxyTrans(liftP))  -- | The 'Maybe' proxy transformer newtype MaybeP p a' a b' b (m :: * -> *) r   = MaybeP { runMaybeP :: p a' a b' b m (Maybe r) } -instance (Monad (p a' a b' b m)) => Functor (MaybeP p a' a b' b m) where-    fmap = liftM+instance (Proxy           p, Monad m)+       => Functor (MaybeP p a' a b' b m) where+    fmap f p = MaybeP (+        runMaybeP p ?>= \m ->+        return_P (case m of+            Nothing -> Nothing+            Just x  -> Just (f x) ) )+ -- fmap f = MaybeP . fmap (fmap f) . runMaybeP -instance (Monad (p a' a b' b m)) => Applicative (MaybeP p a' a b' b m) where-    pure  = return-    (<*>) = ap+instance (Proxy               p, Monad m)+       => Applicative (MaybeP p a' a b' b m) where+    pure = return -instance (Monad (p a' a b' b m)) => Monad (MaybeP p a' a b' b m) where-    return = MaybeP . return . Just-    m >>= f = MaybeP $ do-        ma <- runMaybeP m-        runMaybeP $ case ma of-            Nothing -> nothing-            Just a  -> f a+    fp <*> xp = MaybeP (+        runMaybeP fp ?>= \m1 ->+        case m1 of+            Nothing -> return_P Nothing+            Just f  ->+                runMaybeP xp ?>= \m2 ->+                case m2 of+                    Nothing -> return_P Nothing+                    Just x  -> return_P (Just (f x)) )+ -- fp <*> xp = MaybeP ((<*>) <$> (runMaybeP fp) <*> (runMaybeP xp)) -instance (Monad (p a' a b' b m)) => Alternative (MaybeP p a' a b' b m) where+instance (Proxy         p, Monad m)+       => Monad (MaybeP p a' a b' b m) where+    return = return_P+    (>>=)  = (?>=)++instance (Proxy               p, Monad m)+       => Alternative (MaybeP p a' a b' b m) where     empty = mzero     (<|>) = mplus -instance (Monad (p a' a b' b m)) => MonadPlus (MaybeP p a' a b' b m) where-    mzero = nothing-    mplus m1 m2 = MaybeP $ do-        ma <- runMaybeP m1-        runMaybeP $ case ma of+instance (Proxy              p )+       => MonadPlusP (MaybeP p) where+    mzero_P = nothing+    mplus_P m1 m2 = MaybeP (+        runMaybeP m1 ?>= \ma ->+        runMaybeP (case ma of             Nothing -> m2-            Just a  -> just a+            Just a  -> just a ) ) -instance (MonadTrans (p a' a b' b)) => MonadTrans (MaybeP p a' a b' b) where-    lift = MaybeP . lift . liftM Just+instance (Proxy             p, Monad m)+       => MonadPlus (MaybeP p a' a b' b m) where+    mzero = mzero_P+    mplus = mplus_P -instance (MonadIO (p a' a b' b m)) => MonadIO (MaybeP p a' a b' b m) where-    liftIO = MaybeP . liftIO . liftM Just+instance (Proxy              p )+       => MonadTrans (MaybeP p a' a b' b) where+    lift = lift_P -instance (MFunctor (p a' a b' b)) => MFunctor (MaybeP p a' a b' b) where-    mapT nat = MaybeP . mapT nat . runMaybeP+instance (MonadIOP         p )+       => MonadIOP (MaybeP p) where+    liftIO_P m = MaybeP (liftIO_P (m >>= \x -> return (Just x)))+ -- liftIO = MaybeP . liftIO . liftM Just -instance (Channel p) => Channel (MaybeP p) where-    idT = MaybeP . idT-    p1 >-> p2 = (MaybeP .) $ runMaybeP . p1 >-> runMaybeP . p2+instance (MonadIOP        p, MonadIO m)+       => MonadIO (MaybeP p a' a b' b m) where+    liftIO = liftIO_P +instance (Proxy            p )+       => MFunctor (MaybeP p a' a b' b) where+    hoist = hoist_P++instance (Proxy         p )+       => Proxy (MaybeP p) where+    p1 >-> p2 = \c'1 -> MaybeP (+        ((\b' -> runMaybeP (p1 b')) >-> (\c'2 -> runMaybeP (p2 c'2))) c'1 )+ -- p1 >-> p2 = (MaybeP .) $ runMaybeP . p1 >-> runMaybeP . p2++    p1 >~> p2 = \c'1 -> MaybeP (+        ((\b' -> runMaybeP (p1 b')) >~> (\c'2 -> runMaybeP (p2 c'2))) c'1 )+ -- p1 >~> p2 = (MaybeP .) $ runMaybeP . p1 >~> runMaybeP . p2++    request = \a' -> MaybeP (request a' ?>= \a  -> return_P (Just a ))+    respond = \b  -> MaybeP (respond b  ?>= \b' -> return_P (Just b'))++    return_P = just+    m ?>= f = MaybeP (+        runMaybeP m ?>= \ma ->+        runMaybeP (case ma of+            Nothing -> nothing+            Just a  -> f a ) )++    lift_P m = MaybeP (lift_P (m >>= \x -> return (Just x)))+ -- lift = MaybeP . lift . liftM Just++    hoist_P nat p = MaybeP (hoist_P nat (runMaybeP p))+ -- hoist nat = MaybeP . hoist nat . runMaybeP+ instance ProxyTrans MaybeP where-    liftP = MaybeP . liftM Just+    liftP p = MaybeP (p ?>= \x -> return_P (Just x))+ -- liftP = MaybeP . liftM Just +instance PFunctor MaybeP where+    hoistP nat = MaybeP . nat . runMaybeP+ -- | Run a 'MaybeP' \'@K@\'leisli arrow, returning the result or 'Nothing' runMaybeK :: (q -> MaybeP p a' a b' b m r) -> (q -> p a' a b' b m (Maybe r))-runMaybeK = (runMaybeP .)+runMaybeK p q = runMaybeP (p q)+-- runMaybeK = (runMaybeP .)  -- | A synonym for 'mzero'-nothing :: (Monad (p a' a b' b m)) => MaybeP p a' a b' b m r-nothing = MaybeP $ return Nothing+nothing :: (Monad m, Proxy p) => MaybeP p a' a b' b m r+nothing = MaybeP (return_P Nothing)  -- | A synonym for 'return'-just :: (Monad (p a' a b' b m)) => r -> MaybeP p a' a b' b m r-just = return+just :: (Monad m, Proxy p) => r -> MaybeP p a' a b' b m r+just r = MaybeP (return_P (Just r))
Control/Proxy/Trans/Reader.hs view
@@ -1,6 +1,6 @@ -- | This module provides the proxy transformer equivalent of 'ReaderT'. -{-# LANGUAGE FlexibleContexts, KindSignatures #-}+{-# LANGUAGE KindSignatures #-}  module Control.Proxy.Trans.Reader (     -- * ReaderP@@ -15,91 +15,139 @@     ) where  import Control.Applicative (Applicative(pure, (<*>)), Alternative(empty, (<|>)))-import Control.Monad (liftM, ap, MonadPlus(mzero, mplus))+import Control.Monad (MonadPlus(mzero, mplus)) import Control.Monad.IO.Class (MonadIO(liftIO)) import Control.Monad.Trans.Class (MonadTrans(lift))-import Control.MFunctor (MFunctor(mapT))-import Control.Proxy.Class (-    Channel(idT, (>->)), -    Interact(request, (\>\), respond, (/>/)) )+import Control.MFunctor (MFunctor(hoist))+import Control.PFunctor (PFunctor(hoistP))+import Control.Proxy.Class import Control.Proxy.Trans (ProxyTrans(liftP))  -- | The 'Reader' proxy transformer newtype ReaderP i p a' a b' b (m :: * -> *) r   = ReaderP { unReaderP :: i -> p a' a b' b m r } -instance (Monad (p a' a b' b m)) => Functor (ReaderP i p a' a b' b m) where-    fmap = liftM+instance (Proxy              p, Monad m)+       => Functor (ReaderP i p a' a b' b m) where+    fmap f p = ReaderP (\i ->+        unReaderP p i ?>= \x ->+        return_P (f x) ) -instance (Monad (p a' a b' b m)) => Applicative (ReaderP i p a' a b' b m) where-    pure  = return-    (<*>) = ap+instance (Proxy                  p, Monad m)+       => Applicative (ReaderP i p a' a b' b m) where+    pure = return+    p1 <*> p2 = ReaderP (\i ->+        unReaderP p1 i ?>= \f -> +        unReaderP p2 i ?>= \x -> +        return_P (f x) ) -instance (Monad (p a' a b' b m)) => Monad (ReaderP i p a' a b' b m) where-    return a = ReaderP $ \_ -> return a-    m >>= f = ReaderP $ \i -> do-        a <- unReaderP m i-        unReaderP (f a) i+instance (Proxy            p, Monad m)+       => Monad (ReaderP i p a' a b' b m) where+    return = return_P+    (>>=) = (?>=) -instance (MonadPlus (p a' a b' b m))- => Alternative (ReaderP i p a' a b' b m) where+instance (MonadPlusP             p, Monad m)+       => Alternative (ReaderP i p a' a b' b m) where     empty = mzero     (<|>) = mplus -instance (MonadPlus (p a' a b' b m))- => MonadPlus (ReaderP i p a' a b' b m) where-    mzero = ReaderP $ \_ -> mzero-    mplus m1 m2 = ReaderP $ \i -> mplus (unReaderP m1 i) (unReaderP m2 i)+instance (MonadPlusP           p )+       => MonadPlusP (ReaderP i p) where+    mzero_P = ReaderP (\_ -> mzero_P)+    mplus_P m1 m2 = ReaderP (\i -> mplus_P (unReaderP m1 i) (unReaderP m2 i)) -instance (MonadTrans (p a' a b' b)) => MonadTrans (ReaderP i p a' a b' b) where-    lift m = ReaderP $ \_ -> lift m+instance (MonadPlusP           p, Monad m)+       => MonadPlus (ReaderP i p a' a b' b m) where+    mzero = mzero_P+    mplus = mplus_P -instance (MonadIO (p a' a b' b m)) => MonadIO (ReaderP i p a' a b' b m) where-    liftIO m = ReaderP $ \_ -> liftIO m+instance (Proxy                 p )+       => MonadTrans (ReaderP i p a' a b' b) where+    lift = lift_P -instance (MFunctor (p a' a b' b)) => MFunctor (ReaderP i p a' a b' b) where-    mapT nat = ReaderP . fmap (mapT nat) . unReaderP+instance (MonadIOP            p )+       => MonadIOP (ReaderP i p) where+    liftIO_P m = ReaderP (\_ -> liftIO_P m) -instance (Channel p) => Channel (ReaderP i p) where-    idT a = ReaderP $ \_ -> idT a-    (p1 >-> p2) a = ReaderP $ \i ->-        ((`unReaderP` i) . p1 >-> (`unReaderP` i) . p2) a+instance (MonadIOP           p, MonadIO m)+       => MonadIO (ReaderP i p a' a b' b m) where+    liftIO = liftIO_P -instance (Interact p) => Interact (ReaderP i p) where-    request a = ReaderP $ \_ -> request a-    (p1 \>\ p2) a = ReaderP $ \i ->-        ((`unReaderP` i) . p1 \>\ (`unReaderP` i) . p2) a-    respond a = ReaderP $ \_ -> respond a-    (p1 />/ p2) a = ReaderP $ \i ->-        ((`unReaderP` i) . p1 />/ (`unReaderP` i) . p2) a+instance (Proxy               p )+       => MFunctor (ReaderP i p a' a b' b) where+    hoist = hoist_P +instance (Proxy            p  )+       => Proxy (ReaderP i p) where+    p1 >-> p2 = \c'1 -> ReaderP (\i ->+        ((\b'  -> unReaderP (p1 b' ) i)+     >-> (\c'2 -> unReaderP (p2 c'2) i) ) c'1 )+ {- p1 >-> p2 = \c' -> ReaderP $ \i ->+        ((`unReaderP` i) . p1 >-> (`unReaderP` i) . p2) c' -}++    p1 >~> p2 = \c'1 -> ReaderP (\i ->+        ((\b'  -> unReaderP (p1 b' ) i)+     >~> (\c'2 -> unReaderP (p2 c'2) i) ) c'1 )+ {- p1 >~> p2 = \c' -> ReaderP $ \i ->+        ((`unReaderP` i) . p1 >~> (`unReaderP` i) . p2) c' -}++    return_P = \r -> ReaderP (\_ -> return_P r)+    m ?>= f  = ReaderP (\i ->+        unReaderP m i ?>= \a -> +        unReaderP (f a) i )++    request = \a -> ReaderP (\_ -> request a)+    respond = \a -> ReaderP (\_ -> respond a)++    lift_P m = ReaderP (\_ -> lift_P m)++    hoist_P nat p = ReaderP (\i -> hoist_P nat (unReaderP p i))+ -- hoist_P nat = ReaderP . fmap (hoist_P nat) . unReaderP++instance (Interact            p)+       => Interact (ReaderP i p) where+    p1 \>\ p2 = \c'1 -> ReaderP (\i ->+        ((\b'  -> unReaderP (p1 b' ) i)+     \>\ (\c'2 -> unReaderP (p2 c'2) i) ) c'1 )+ {- p1 \>\ p2 = \c' -> ReaderP $ \i ->+        ((`unReaderP` i) . p1 \>\ (`unReaderP` i) . p2) c' -}++    p1 />/ p2 = \a1 -> ReaderP (\i ->+        ((\b  -> unReaderP (p1 b ) i)+     />/ (\a2 -> unReaderP (p2 a2) i) ) a1 )+ {- p1 />/ p2 = \a -> ReaderP $ \i ->+        ((`unReaderP` i) . p1 />/ (`unReaderP` i) . p2) a -}+ instance ProxyTrans (ReaderP i) where-    liftP m = ReaderP $ \_ -> m+    liftP m = ReaderP (\_ -> m) +instance PFunctor (ReaderP i) where+    hoistP nat = ReaderP . (nat .) . unReaderP+ -- | Run a 'ReaderP' computation, supplying the environment runReaderP :: i -> ReaderP i p a' a b' b m r -> p a' a b' b m r runReaderP i m = unReaderP m i  -- | Run a 'ReaderP' \'@K@\'leisli arrow, supplying the environment runReaderK :: i -> (q -> ReaderP i p a' a b' b m r) -> (q -> p a' a b' b m r)-runReaderK i = (runReaderP i .)+runReaderK i p q = runReaderP i (p q)+-- runReaderK i = (runReaderP i .)  -- | Modify a computation's environment (a more general version of 'local') withReaderP- :: (Monad (p a' a b' b m))- => (j -> i) -> ReaderP i p a' a b' b m r -> ReaderP j p a' a b' b m r-withReaderP f r = ReaderP $ unReaderP r . f+ :: (j -> i) -> ReaderP i p a' a b' b m r -> ReaderP j p a' a b' b m r+withReaderP f p = ReaderP (\i -> unReaderP p (f i))+-- withReaderP f p = ReaderP $ unReaderP p . f  -- | Get the environment-ask :: (Monad (p a' a b' b m)) => ReaderP i p a' a b' b m i-ask = ReaderP return+ask :: (Proxy p, Monad m) => ReaderP i p a' a b' b m i+ask = ReaderP return_P  -- | Get a function of the environment-asks :: (Monad (p a' a b' b m)) => (i -> r) -> ReaderP i p a' a b' b m r-asks f = ReaderP (return . f)+asks :: (Proxy p, Monad m) => (i -> r) -> ReaderP i p a' a b' b m r+asks f = ReaderP (\i -> return_P (f i))  -- | Modify a computation's environment (a specialization of 'withReaderP') local- :: (Monad (p a' a b' b m))- => (i -> i) -> ReaderP i p a' a b' b m r -> ReaderP i p a' a b' b m r+ :: (i -> i) -> ReaderP i p a' a b' b m r -> ReaderP i p a' a b' b m r local = withReaderP
Control/Proxy/Trans/State.hs view
@@ -1,8 +1,6 @@-{-| This module provides the proxy transformer equivalent of 'StateT'.--    Sequencing of computations is strict. -}+-- | This module provides the proxy transformer equivalent of 'StateT'. -{-# LANGUAGE FlexibleContexts, KindSignatures #-}+{-# LANGUAGE KindSignatures #-}  module Control.Proxy.Trans.State (     -- * StateP@@ -21,98 +19,148 @@     ) where  import Control.Applicative (Applicative(pure, (<*>)), Alternative(empty, (<|>)))-import Control.Monad (liftM, ap, MonadPlus(mzero, mplus))+import Control.Monad (MonadPlus(mzero, mplus)) import Control.Monad.IO.Class (MonadIO(liftIO)) import Control.Monad.Trans.Class (MonadTrans(lift))-import Control.MFunctor (MFunctor(mapT))-import Control.Proxy.Class (Channel(idT, (>->)))+import Control.MFunctor (MFunctor(hoist))+import Control.PFunctor (PFunctor(hoistP))+import Control.Proxy.Class import Control.Proxy.Trans (ProxyTrans(liftP)) --- | The strict 'State' proxy transformer+-- | The 'State' proxy transformer newtype StateP s p a' a b' b (m :: * -> *) r   = StateP { unStateP :: s -> p a' a b' b m (r, s) } -instance (Monad (p a' a b' b m)) => Functor (StateP s p a' a b' b m) where-    fmap = liftM+instance (Proxy             p, Monad m)+       => Functor (StateP s p a' a b' b m) where+       fmap f p = StateP (\s0 ->+           unStateP p s0 ?>= \(x, s1) ->+           return_P (f x, s1) ) -instance (Monad (p a' a b' b m)) => Applicative (StateP s p a' a b' b m) where-    pure  = return-    (<*>) = ap+{- As far as I can tell, there is no way to write this using an Applicative+   context -}+instance (Proxy                 p, Monad m)+       => Applicative (StateP s p a' a b' b m) where+    pure = return+    p1 <*> p2 = StateP (\s0 ->+        unStateP p1 s0 ?>= \(f, s1) ->+        unStateP p2 s1 ?>= \(x, s2) ->+        return_P (f x, s2) ) -instance (Monad (p a' a b' b m)) => Monad (StateP s p a' a b' b m) where-    return a = StateP $ \s -> return (a, s)-    m >>= f = StateP $ \s -> do-        (a, s') <- unStateP m s-        unStateP (f a) s'+instance (Proxy           p, Monad m)+       => Monad (StateP s p a' a b' b m) where+    return = return_P+    (>>=)  = (?>=) -instance (MonadPlus (p a' a b' b m))- => Alternative (StateP s p a' a b' b m) where+instance (MonadPlusP            p, Monad m)+       => Alternative (StateP s p a' a b' b m) where     empty = mzero     (<|>) = mplus -instance (MonadPlus (p a' a b' b m)) => MonadPlus (StateP s p a' a b' b m) where-    mzero = StateP $ \_ -> mzero-    mplus m1 m2 = StateP $ \s -> mplus (unStateP m1 s) (unStateP m2 s)+instance (MonadPlusP           p )+       => MonadPlusP (StateP s p) where+    mzero_P       = StateP (\_ -> mzero_P)+    mplus_P m1 m2 = StateP (\s -> mplus_P (unStateP m1 s) (unStateP m2 s)) -instance (MonadTrans (p a' a b' b)) => MonadTrans (StateP s p a' a b' b) where-    lift m = StateP $ \s -> lift $ liftM (\r -> (r, s)) m+instance (MonadPlusP          p, Monad m)+       => MonadPlus (StateP s p a' a b' b m) where+    mzero = mzero_P+    mplus = mplus_P -instance (MonadIO (p a' a b' b m)) => MonadIO (StateP s p a' a b' b m) where-    liftIO m = StateP $ \s -> liftIO $ liftM (\r -> (r, s)) m+instance (Proxy                p )+       => MonadTrans (StateP s p a' a b' b) where+    lift = lift_P -instance (MFunctor (p a' a b' b)) => MFunctor (StateP s p a' a b' b) where-    mapT nat = StateP . fmap (mapT nat) . unStateP+instance (MonadIOP           p )+       => MonadIOP (StateP s p) where+    liftIO_P m = StateP (\s -> liftIO_P (m >>= \r -> return (r, s))) -instance (Channel p) => Channel (StateP s p) where-    idT a = StateP $ \_ -> idT a-    (p1 >-> p2) a = StateP $ \s ->-        ((`unStateP` s) . p1 >-> (`unStateP` s) . p2) a+instance (MonadIOP          p, MonadIO m)+       => MonadIO (StateP s p a' a b' b m) where+    liftIO = liftIO_P +instance (Proxy              p )+       => MFunctor (StateP s p a' a b' b) where+    hoist = hoist_P++instance (Proxy           p )+       => Proxy (StateP s p) where+    p1 >-> p2 = \c'1 -> StateP (\s ->+        ((\b' -> unStateP (p1 b') s) >-> (\c'2 -> unStateP (p2 c'2) s)) c'1 )+ {- (p1 >-> p2) = \c' -> StateP $ \s ->+        ((`unStateP` s) . p1 >-> (`unStateP` s) . p2) c' -}++    p1 >~> p2 = \c'1 -> StateP (\s ->+        ((\b' -> unStateP (p1 b') s) >~> (\c'2 -> unStateP (p2 c'2) s)) c'1 )+ {- (p1 >~> p2) = \c' -> StateP $ \s ->+        ((`unStateP` s) . p1 >~> (`unStateP` s) . p2) c' -}++    request = \a' -> StateP (\s -> request a' ?>= \a  -> return_P (a , s))+    respond = \b  -> StateP (\s -> respond b  ?>= \b' -> return_P (b', s))++    return_P = \r -> StateP (\s -> return_P (r, s))+    m ?>= f  = StateP (\s ->+        unStateP m s ?>= \(a, s') ->+        unStateP (f a) s' )++    lift_P m = StateP (\s -> lift_P (m >>= \r -> return (r, s)))++    hoist_P nat p = StateP (\s -> hoist_P nat (unStateP p s))+ -- hoist nat = StateP . fmap (hoist nat) . unStateP+ instance ProxyTrans (StateP s) where-    liftP m = StateP $ \s -> liftM (\r -> (r, s)) m+    liftP m = StateP (\s -> m ?>= \r -> return_P (r, s)) +instance PFunctor (StateP s) where+    hoistP nat = StateP . (nat .) . unStateP+ -- | Run a 'StateP' computation, producing the final result and state runStateP :: s -> StateP s p a' a b' b m r -> p a' a b' b m (r, s) runStateP s m = unStateP m s  -- | Run a 'StateP' \'@K@\'leisli arrow, procuding the final result and state runStateK :: s -> (q -> StateP s p a' a b' b m r) -> (q -> p a' a b' b m (r, s))-runStateK s = (runStateP s .)+runStateK s k q = unStateP (k q) s+-- runStateK s = (runStateP s .)  -- | Evaluate a 'StateP' computation, but discard the final state evalStateP- :: (Monad (p a' a b' b m)) => s -> StateP s p a' a b' b m r -> p a' a b' b m r-evalStateP s = liftM fst . runStateP s+ :: (Proxy p, Monad m) => s -> StateP s p a' a b' b m r -> p a' a b' b m r+evalStateP s p = unStateP p s ?>= \x -> return_P (fst x)+-- evalStateP s = liftM fst . runStateP s  -- | Evaluate a 'StateP' \'@K@\'leisli arrow, but discard the final state evalStateK- :: (Monad (p a' a b' b m))+ :: (Proxy p, Monad m)  => s -> (q -> StateP s p a' a b' b m r) -> (q -> p a' a b' b m r)-evalStateK s = (evalStateP s .)+evalStateK s k q = evalStateP s (k q)+-- evalStateK s = (evalStateP s .)  -- | Evaluate a 'StateP' computation, but discard the final result execStateP- :: (Monad (p a' a b' b m)) => s -> StateP s p a' a b' b m r -> p a' a b' b m s-execStateP s = liftM snd . runStateP s+ :: (Proxy p, Monad m) => s -> StateP s p a' a b' b m r -> p a' a b' b m s+execStateP s p = unStateP p s ?>= \x -> return_P (snd x)+-- execStateP s = liftM snd . runStateP s  -- | Evaluate a 'StateP' \'@K@\'leisli arrow, but discard the final result execStateK- :: (Monad (p a' a b' b m))+ :: (Proxy p, Monad m)  => s -> (q -> StateP s p a' a b' b m r) -> (q -> p a' a b' b m s)-execStateK s = (execStateP s .)+execStateK s k q = execStateP s (k q)+-- execStateK s = (execStateP s .)  -- | Get the current state-get :: (Monad (p a' a b' b m)) => StateP s p a' a b' b m s-get = StateP $ \s -> return (s, s)+get :: (Proxy p, Monad m) => StateP s p a' a b' b m s+get = StateP (\s -> return_P (s, s))  -- | Set the current state-put :: (Monad (p a' a b' b m)) => s -> StateP s p a' a b' b m ()-put s = StateP $ \_ -> return ((), s)+put :: (Proxy p, Monad m) => s -> StateP s p a' a b' b m ()+put s = StateP (\_ -> return_P ((), s))  -- | Modify the current state using a function-modify :: (Monad (p a' a b' b m)) => (s -> s) -> StateP s p a' a b' b m ()-modify f = StateP $ \s -> return ((), f s)+modify :: (Proxy p, Monad m) => (s -> s) -> StateP s p a' a b' b m ()+modify f = StateP (\s -> return_P ((), f s))  -- | Get the state filtered through a function-gets :: (Monad (p a' a b' b m)) => (s -> r) -> StateP s p a' a b' b m r-gets f = StateP $ \s -> return (f s, s)+gets :: (Proxy p, Monad m) => (s -> r) -> StateP s p a' a b' b m r+gets f = StateP (\s -> return_P (f s, s))
− Control/Proxy/Trans/Tutorial.hs
@@ -1,415 +0,0 @@--- | This module provides the tutorial for the "Control.Proxy.Trans" hierarchy--module Control.Proxy.Trans.Tutorial (-    -- * Motivation-    -- $motivation--    -- * Proxy Transformers-    -- $proxytrans--    -- * Compatibility-    -- $compatibility--    -- * Proxy Transformer Stacks-    -- $stacks-    ) where--import Control.Monad.Trans.Class-import Control.Monad.Trans.State-import Control.Proxy-import Control.Proxy.Trans.Either-import Control.Proxy.Trans.State--{- $motivation-    In a 'Session', all composed proxies share effects within the base monad.-    To see how, consider the following simple 'Session':--> client1 :: () -> Client () () (StateT Int IO) r-> client1 () = forever $ do->     s <- lift get->     lift $ lift $ putStrLn $ "Client: " ++ show s->     lift $ put (s + 1)->     request ()->-> server1 :: () -> Server () () (StateT Int IO) r-> server1 () = forever $ do->     s <- lift get->     lift $ lift $ putStrLn $ "Server: " ++ show s->     lift $ put (s + 1)->     respond ()-->>> (`evalStateT` 0) $ runProxy $ client1 <-< server1-Client: 0-Server: 1-Client: 2-Server: 3-Client: 4-Server: 5-...--    The client and server share the same state, which is sometimes not what we-    want.  We can easily solve this by running each 'Proxy' with its own local-    state by changing the order of the 'Proxy' and 'StateT' monad transformers:--> client2 :: () -> StateT Int (Client () () IO) r-> client2 () = forever $ do->     s <- get->     lift $ lift $ putStrLn $ "Client: " ++ show s->     put (s + 1)->     lift $ request ()->-> server2 :: () -> StateT Int (Server () () IO) r-> server2 () = forever $ do->     s <- get->     lift $ lift $ putStrLn $ "Server: " ++ show s->     put (s + 1)->     lift $ respond ()--    ... but then we can no longer compose them directly.  We have to first-    unwrap each one with 'evalStateT' before composing:-->>> runProxy $ (`evalStateT` 0) . client2 <-< (`evalStateT` 0) . server2-Client: 0-Server: 0-Client: 1-Server: 1-Client: 2-Server: 2-...--    Here's another example: suppose we want to handle errors within proxies.  We-    could try adding 'EitherT' to the base monad like so:--> import Control.Error->-> client3 :: () -> Client () () (EitherT String IO) ()-> client3 () = forM_ [1..] $ \i -> do->     lift $ lift $ print i->     request ()->-> server3 :: (Monad m) => () -> Server () () (EitherT String m) r-> server3 () = lift $ left "ERROR"-->>> runEithert $ runProxy $ client2 <-< server2-1-Left "ERROR"--    Unfortunately, we can't modify @server2@ to 'catchT' that error because we-    cannot access the inner 'EitherT' monad transformer until we run the-    'Session'.  We'd really prefer to place the 'EitherT' monad transformer-    /outside/ the 'Proxy' monad transformer so that we can catch and handle-    errors locally within a 'Proxy' without disturbing other proxies:--> client4 :: () -> EitherT String (Client () () IO) ()-> client4 () = forM_ [1..] $ \i -> do->     lift $ lift $ print i->     lift $ request ()->-> server4 :: () -> EitherT String (Server () () IO) ()-> server4 () = (forever $ do->     lift $ respond ()->     throwT "Error" )->   `catchT` (\str -> do->         lift $ lift $ putStrLn $ "Caught: " ++ str->         server4 () )--    However, this solution similarly requires unwrapping the client and server-    using 'runEitherT' before composing them:-->>> runProxy $ runEitherT . client4 <-< runEitherT . server4-1-Caught: Error-2-Caught: Error-3-Caught: Error-...---}--{- $proxytrans-    We need some way to layer monad transformers /outside/ the proxy type-    without interfering with 'Proxy' composition.  To do this, we overload-    'Proxy' composition using the 'Channel' type class from-    "Control.Proxy.Class":--> class Channel p where->     idT :: (Monad) m => a' -> p a' a a' a m r->     (>->)->      :: (Monad m)->      => (b' -> p a' a b' b m r)->      -> (c' -> p b' b c' c m r)->      -> (c' -> p a' a c' c m r)--    Obviously, 'Proxy' implements this class:--> instance Channel Proxy where ...--    ... but we would also like our monad transformers layered outside the-    'Proxy' type to also implement the 'Channel' class so that we could compose-    them directly without unwrapping.  Unfortunately, these monad transformers-    do not fit the signature of the 'Channel' class.--    Fortunately, the "Control.Proxy.Trans" hierarchy provides several common-    monad transformers which have been upgraded to fit the 'Channel' type class.-    I call these \"proxy transformers\".--    For example, "Control.Proxy.Trans.State" provides a proxy transformer-    equivalent to @Control.Monad.Trans.State@.  Similarly,-    "Control.Proxy.Trans.Either" provides a proxy transformer equivalent to-    @Control.Monad.Trans.Either@.--    Let's use a working code example to demonstrate how to use them:--> import Control.Proxy.Trans.State-> -> client5 :: () -> StateP Int Proxy () () () C IO r-> client5 () = forever $ do->     s <- get->     liftP $ lift $ putStrLn $ "Client: " ++ show s->     put (s + 1)->     liftP $ request ()->-> server5 :: () -> StateP Int Proxy C () () () IO r-> server5 () = forever $ do->     s <- get->     liftP $ lift $ putStrLn $ "Server: " ++ show s->     put (s + 1)->     liftP $ respond ()--    You'll see that our type signatures changed.  Now we use 'StateP' instead of-    'StateT'.  However, 'StateP' does not transform monads, but instead-    transforms proxies.--    To see this, let's first study the kind of 'StateT'.  If we first define:--> kind MonadKind = * -> *--    Then @StateT s@ takes a monad, and returns a new monad:--> StateT s :: MonadKind -> MonadKind--    Now consider the kind of a 'Proxy'-like type constructor suitable for the-    'Channel' type class:--> kind ProxyKind = * -> * -> * -> * -> (* -> *) -> * -> *--    Then @StateP s@  takes a 'Proxy'-like and returns a new 'Proxy'-like type:--> StateP s :: ProxyKind -> ProxyKind--    This is why I call these \"proxy transformers\" and not monad transformers.-    They all take some 'Proxy'-like type that implements 'Channel' and transform-    it into a new 'Proxy'-like type that also implements 'Channel'.  For-    example, 'StateP' implement the following instance:--> instance (Channel p) => Channel (StateP s p) where ...--    All proxy transformers guarantee that if the base proxy implements the-    'Channel' type class, then the transformed proxy also implements the-    'Channel' type class.  This means that you can build a proxy transformer-    stack, just like you might build a monad transformer stack.--    Unfortunately, in order to use proxy transformers, you must expand out the-    'Client' and 'Server' type synonyms, which are not compatible with proxy-    transformers.  Sorry!  This is why there are no 'Server' or 'Client' type-    synonyms in the types of our new client and server and I had to write out-    all the inputs and outputs.--    Notice how the outermost 'lift' statements in our client and server have-    changed to 'liftP'.  'liftP' replaces 'lift' for proxy transformers, and it-    lifts any action in the base proxy to an action in the transformed proxy.-    In the previous example, the base proxy was 'Proxy' and the transformed-    proxy was @StateP s Proxy@, so 'liftP's type got specialized to:--> liftP :: Proxy a' a b' b m r -> StateP s Proxy a' a b' b m r--    The 'ProxyTrans' class defines 'liftP', and all proxy transformers implement-    the 'ProxyTrans' class.  Since proxies are still monads, 'liftP' must-    behave just like 'lift' and obey the monad transformer laws:--> (liftP .) return = return->-> (liftP .) (f >=> g) = (liftP .) f >=> (liftP .) g--    But, unlike 'lift', 'liftP' obeys one extra set of laws that guarantee it -    also lifts composition sensibly:--> (liftP .) idT = idT->-> (liftP .) (f >-> g) = (liftP .) f >-> (liftP .) g--    In fact, this @(liftP .)@ pattern is so ubiquitous, that the 'ProxyTrans'-    class provides the additional 'mapP' method for convenience:--> mapP = (liftP .)--    Proxy transformers automatically derive how to lift composition correctly-    and also guarantee that the derived composition obeys the category laws if-    the base composition obeyed the category laws.  Since 'Proxy' composition-    obeys the category laws, any proxy transformer stack built on top of it-    automatically derives a composition operation that is correct by-    construction.--    Let's prove this by directly composing our 'StateP'-extended proxies without-    unwrapping them:--> :t client5 <-< server5 :: () -> StateP Int Proxy C () () C IO r--    However, we still have to unwrap the final 'StateP' 'Session' before we can-    pass it to 'runProxy'.  We use 'runStateK' for this purpose:-->>> runProxy $ runStateK 0 $ client5 <-< server5-Client: 0-Server: 0-Client: 1-Server: 1-Client: 2-Server: 2-Client: 3-Server: 3-...--    Keep in mind that 'runStateK' takes the initial state as its first argument,-    unlike 'runStateT'.  I break from the @transformers@ convention for-    syntactic convenience.--    We can similarly fix our 'EitherT' example, using 'EitherP' from-    "Control.Proxy.Trans.Either":--> import Control.Proxy.Trans.Either as E->-> client6 :: () -> EitherP String Proxy () () () C IO ()-> client6 () = forM_ [1..] $ \i -> do->     liftP $ lift $ print i->     liftP $ request ()->-> server6 :: () -> EitherP String Proxy C () () () IO ()-> server6 () = (forever $ do->     liftP $ respond ()->     E.throw "Error" )->   `E.catch` (\str -> do->         liftP $ lift $ putStrLn $ "Caught: " ++ str->         server6 () )-->>> runProxy $ runEitherK $ client6 <-< server6-1-Caught: Error-2-Caught: Error-3-Caught: Error-...---}--{- $compatibility-    Proxy transformers do more than just lift composition.  They automatically-    promote proxies written in the base monad.  For example, what if I wanted to-    use the 'takeB_' proxy from "Control.Proxy.Prelude.Base" to cap the number-    of results?  I can't compose it directly because it uses the 'Proxy' type:--> takeB_ :: (Monad m) => Int -> a' -> Proxy a' a a' a m ()--    ... whereas @client6@ and @server6@ use @EitherP String Proxy@.  However,-    this doesn't matter because we can automatically lift 'takeB_' to be-    compatible with them using 'mapP':-->>> runProxy $ runEitherK $ client6 <-< mapP (takeB_ 2) <-< server6-1-Caught: Error-2-Caught:Error--    'mapP' promotes any proxy written using the base proxy type to automatically-    be compatible with proxies written using the extended proxy type.  This-    means you can safely write utility proxies using the smallest feature set-    they require and promote them as necessary to work with more extended-    feature sets.  This ensures that any proxies you write always remain-    forwards-compatible as people write new extensions.--}--{- $stacks-    You can stack proxy transformers to combine their effects, such as in the-    following example, which combines everything we've used so far:--> client7 :: () -> EitherP String (StateP Int Proxy) () Int () C IO r-> client7 () = do->     n <- liftP get->     liftP $ liftP $ lift $ print n->     n' <- liftP $ liftP $ request ()->     liftP $ put n'->     E.throw "ERROR"-->>> runProxy $ runStateK 0 $ runEitherK $ client7 <-< mapP (mapP (enumFromS 1))-0-(Left "Error", 1)--    But that's still not the full story!  For calls to the base monad (i.e. 'IO'-    in this case), you don't need to precede them with all those 'liftP's.-    Every proxy transformer also correctly derives 'MonadTrans', so you can dig-    straight to the base monad by just calling 'lift' at the outer-most level:--> client7 :: () -> EitherP String (StateP Int Proxy) () Int () C IO r-> client7 () = do->     n <- liftP get->     lift $ print n  -- Much better!->     n' <- liftP $ liftP $ request ()->     liftP $ put n'->     E.throw "ERROR"--    Also, you can combine multiple proxy transformers into a single proxy-    transformer, just like you would with monad transformers:--> newtype BothP e s p a' a b' b m r =->     BothP { unBothP :: EitherP e (StateP s p) a' a b' b m r }->     deriving (Functor, Applicative, Monad, MonadTrans, Channel)-> -> instance ProxyTrans (BothP e s) where->     liftP = BothP . liftP . liftP-> -> runBoth->  :: (Monad m)->  => s->  -> (b' -> BothP e s p a' a b' b m r)->  -> (b' -> p a' a b' b m (Either e r, s))-> runBoth s = runStateK s . runEitherK . fmap unBothP-> -> get' :: (Monad (p a' a b' b m), Channel p)->      => BothP e s p a' a b' b m s-> get' = BothP $ liftP get-> -> put' :: (Monad (p a' a b' b m), Channel p)->      => s -> BothP e s p a' a b' b m ()-> put' x = BothP $ liftP $ put x-> -> throw' :: (Monad (p a' a b' b m), Channel p)->        => e -> BothP e s p a' a b' b m r-> throw' e = BothP $ E.throw e--    Then we can write proxies using this new proxy transformer of ours:--> client8 :: () -> BothP String Int Proxy () Int () C IO r-> client8 () = do->     n <- get'->     lift $ print n->     n' <- liftP $ request ()->     put' n'->     throw' "ERROR"-->>> runProxy $ runBoth 0 $ client8 <-< mapP (enumFromS 1)-0-(Left "ERROR",1)--    Note that 'request' and 'respond' are not automatically liftable, because of-    technical limitations with Haskell type classes.  When I resolve these-    issues they will also be automatically promoted by proxy transformers.  For-    now, you must lift them manually using 'liftP':--> request = (liftP .) request-> respond = (liftP .) respond--    The left 'request' and 'respond' in the above equations are what the lifted-    definitions would be for each proxy transformer if Haskell's type class-    system didn't get in my way.--}
Control/Proxy/Trans/Writer.hs view
@@ -6,7 +6,7 @@     The underlying implementation uses the state monad to avoid quadratic blowup     from left-associative binds. -} -{-# LANGUAGE FlexibleContexts, KindSignatures #-}+{-# LANGUAGE KindSignatures #-}  module Control.Proxy.Trans.Writer (     -- * WriterP@@ -21,11 +21,12 @@     ) where  import Control.Applicative (Applicative(pure, (<*>)), Alternative(empty, (<|>)))-import Control.Monad (liftM, ap, MonadPlus(mzero, mplus))+import Control.Monad (MonadPlus(mzero, mplus)) import Control.Monad.IO.Class (MonadIO(liftIO)) import Control.Monad.Trans.Class (MonadTrans(lift))-import Control.MFunctor (MFunctor(mapT))-import Control.Proxy.Class (Channel(idT, (>->)))+import Control.MFunctor (MFunctor(hoist))+import Control.PFunctor (PFunctor(hoistP))+import Control.Proxy.Class import Control.Proxy.Trans (ProxyTrans(liftP)) import Data.Monoid (Monoid(mempty, mappend)) @@ -33,51 +34,88 @@ newtype WriterP w p a' a b' b (m :: * -> *) r   = WriterP { unWriterP :: w -> p a' a b' b m (r, w) } -instance (Monad (p a' a b' b m))- => Functor (WriterP w p a' a b' b m) where-    fmap = liftM+instance (Proxy              p, Monad m)+       => Functor (WriterP w p a' a b' b m) where+    fmap f p = WriterP (\w0 ->+        unWriterP p w0 ?>= \(x, w1) ->+        return_P (f x, w1) ) -instance (Monad (p a' a b' b m))- => Applicative (WriterP w p a' a b' b m) where-    pure  = return-    (<*>) = ap+instance (Proxy                  p, Monad m)+       => Applicative (WriterP w p a' a b' b m) where+    pure = return+    fp <*> xp = WriterP (\w0 ->+        unWriterP fp w0 ?>= \(f, w1) ->+        unWriterP xp w1 ?>= \(x, w2) ->+        return_P (f x, w2) )+ -- (<*>) = ap -instance (Monad (p a' a b' b m))- => Monad (WriterP w p a' a b' b m) where-    return a = WriterP $ \w -> return (a, w)-    m >>= f = WriterP $ \w -> do-        (a, w') <- unWriterP m w-        unWriterP (f a) w'+instance (Proxy            p, Monad m)+       => Monad (WriterP w p a' a b' b m) where+    return = return_P+    (>>=) = (?>=) -instance (MonadPlus (p a' a b' b m))- => Alternative (WriterP w p a' a b' b m) where+instance (MonadPlusP             p, Monad m)+       => Alternative (WriterP w p a' a b' b m) where     empty = mzero     (<|>) = mplus -instance (MonadPlus (p a' a b' b m))- => MonadPlus (WriterP w p a' a b' b m) where-    mzero = WriterP $ \_ -> mzero-    mplus m1 m2 = WriterP $ \w -> mplus (unWriterP m1 w) (unWriterP m2 w)+instance (MonadPlusP            p )+       => MonadPlusP (WriterP w p) where+    mzero_P       = WriterP (\_ -> mzero_P)+    mplus_P m1 m2 = WriterP (\w -> mplus_P (unWriterP m1 w) (unWriterP m2 w)) -instance (MonadTrans (p a' a b' b))- => MonadTrans (WriterP w p a' a b' b) where-    lift m = WriterP $ \w -> lift $ liftM (\r -> (r, w)) m+instance (MonadPlusP           p, Monad m)+       => MonadPlus (WriterP w p a' a b' b m) where+    mzero = mzero_P+    mplus = mplus_P -instance (MonadIO (p a' a b' b m))- => MonadIO (WriterP w p a' a b' b m) where-    liftIO m = WriterP $ \w ->  liftIO $ liftM (\r -> (r, w)) m+instance (Proxy                 p )+       => MonadTrans (WriterP w p a' a b' b) where+    lift = lift_P -instance (MFunctor (p a' a b' b)) => MFunctor (WriterP w p a' a b' b) where-    mapT nat = WriterP . fmap (mapT nat) . unWriterP+instance (MonadIOP            p )+       => MonadIOP (WriterP w p) where+    liftIO_P m = WriterP (\w -> liftIO_P (m >>= \r -> return (r, w))) -instance (Channel p) => Channel (WriterP w p) where-    idT a = WriterP $ \_ -> idT a-    (p1 >-> p2) a = WriterP $ \w ->-        ((`unWriterP` w) . p1 >-> (`unWriterP` w) . p2) a+instance (MonadIOP           p, MonadIO m)+       => MonadIO (WriterP w p a' a b' b m) where+    liftIO = liftIO_P -instance (Monoid w) => ProxyTrans (WriterP w) where-    liftP m = WriterP $ \w -> liftM (\r -> (r, w)) m+instance (Proxy               p )+       => MFunctor (WriterP w p a' a b' b) where+    hoist = hoist_P +instance (Proxy            p )+       => Proxy (WriterP w p) where+    p1 >-> p2 = \c'1 -> WriterP (\w ->+        ((\b' -> unWriterP (p1 b') w) >-> (\c'2 -> unWriterP (p2 c'2) w)) c'1 )+ {- p1 >-> p2 = \c' -> WriterP $ \w ->+        ((`unWriterP` w) . p1 >-> (`unWriterP` w) . p2) c' -}++    p1 >~> p2 = \c'1 -> WriterP (\w ->+        ((\b' -> unWriterP (p1 b') w) >~> (\c'2 -> unWriterP (p2 c'2) w)) c'1 )+ {- p1 >~> p2 = \c' -> WriterP $ \w ->+        ((`unWriterP` w) . p1 >~> (`unWriterP` w) . p2) c' -}++    request = \a' -> WriterP (\w -> request a' ?>= \a  -> return_P (a,  w))+    respond = \b  -> WriterP (\w -> respond b  ?>= \b' -> return_P (b', w))++    return_P = \r -> WriterP (\w -> return_P (r, w))+    m ?>= f  = WriterP (\w ->+        unWriterP m w ?>= \(a, w') ->+        unWriterP (f a) w' )++    lift_P m = WriterP (\w -> lift_P (m >>= \r -> return (r, w)))++    hoist_P nat p = WriterP (\w -> hoist_P nat (unWriterP p w))+ -- hoist_P nat = WriterP . fmap (hoist_P nat) . unWriterP++instance ProxyTrans (WriterP w) where+    liftP m = WriterP (\w -> m ?>= \r -> return_P (r, w))++instance PFunctor (WriterP w) where+    hoistP nat = WriterP . (nat .) . unWriterP+ -- | Run a 'WriterP' computation, producing the final result and monoid runWriterP :: (Monoid w) => WriterP w p a' a b' b m r -> p a' a b' b m (r, w) runWriterP p = unWriterP p mempty@@ -86,26 +124,31 @@ runWriterK  :: (Monoid w)  => (q -> WriterP w p a' a b' b m r) -> (q -> p a' a b' b m (r, w))-runWriterK = (runWriterP . )+runWriterK k q = runWriterP (k q)+-- runWriterK = (runWriterP . )  -- | Evaluate a 'WriterP' computation, but discard the final result execWriterP- :: (Monad (p a' a b' b m), Monoid w)+ :: (Proxy p, Monad m, Monoid w)  => WriterP w p a' a b' b m r -> p a' a b' b m w-execWriterP m = liftM snd $ runWriterP m+execWriterP m = runWriterP m ?>= \(_, w) -> return_P w+-- execWriterP m = liftM snd $ runWriterP m  -- | Evaluate a 'WriterP' \'@K@\'leisli arrow, but discard the final result execWriterK- :: (Monad (p a' a b' b m), Monoid w)+ :: (Proxy p, Monad m, Monoid w)  => (q -> WriterP w p a' a b' b m r) -> (q -> p a' a b' b m w)-execWriterK = (execWriterP .)+execWriterK k q= execWriterP (k q)  -- | Add a value to the monoid-tell :: (Monad (p a' a b' b m), Monoid w) => w -> WriterP w p a' a b' b m ()-tell w' = WriterP $ \w -> let w'' = mappend w w' in w'' `seq` return ((), w'')+tell :: (Proxy p, Monad m, Monoid w) => w -> WriterP w p a' a b' b m ()+tell w' = WriterP (\w -> let w'' = mappend w w' in w'' `seq` return_P ((), w''))  -- | Modify the result of a writer computation censor- :: (Monad (p a' a b' b m), Monoid w)+ :: (Proxy p, Monad m, Monoid w)  => (w -> w) -> WriterP w p a' a b' b m r -> WriterP w p a' a b' b m r-censor f = WriterP . fmap (liftM (\(a, w) -> (a, f w))) . unWriterP+censor f p = WriterP (\w0 ->+    unWriterP p w0 ?>= \(r, w1) ->+    return_P (r, f w1) )+-- censor f = WriterP . fmap (liftM (\(r, w) -> (r, f w))) . unWriterP
Control/Proxy/Tutorial.hs view
@@ -1,550 +1,1890 @@--- | This module provides the tutorial for "Control.Proxy"--module Control.Proxy.Tutorial (-    -- * Basics-    -- $basics--    -- * Types-    -- $types--    -- * Composition-    -- $composition--    -- * Idioms-    -- $idioms--    -- * Reusability-    -- $reuse--    -- * Mixing monads and composition-    -- $monads--    -- * Utility proxies-    -- $utility--    -- * Pipe compatibility-    -- $pipes-    ) where--import Control.Monad.Trans.Class-import Control.Proxy--{- $basics-    The 'Proxy' type models composable chains of client-server interactions.--    A 'Proxy' is a monad transformer that extends the base monad with the-    ability to 'request' input from upstream and 'respond' with output to-    downstream.--    For example, consider the following toy remote procedure call-    'Server':--> import Control.Proxy-> import Control.Monad.Trans->-> incrementer :: Int -> Server Int Int IO r-> incrementer question = do->     lift $ putStrLn $ "Server received : " ++ show question->     let answer = question + 1->     lift $ putStrLn $ "Server responded: " ++ show answer->     nextQuestion <- respond answer->     incrementer nextQuestion--    We can understand what the 'Server' does just by looking at the type:-->        | Question | Answer | Base monad | Return value-> Server   Int        Int        IO           r--    Our 'Server' receives questions about 'Int's, and responds with answers that-    are 'Int's.  The base monad is 'IO' because our 'Server' 'lift's two-    'putStrLn' statements to chat out loud.  The return value is polymorphic-    because our 'Server' never terminates.--    Note that the base monad doesn't always need to be 'IO'.  Unlike typical-    servers, these kinds of 'Server's are pure syntax trees with no side-    effects unless you call 'lift'.--    Now we can write a 'Client' that interacts with our 'Server':--> import Control.Monad->-> oneTwoThree :: () -> Client Int Int IO ()-> oneTwoThree () = forM_ [1, 2, 3] $ \question -> do->     lift $ putStrLn $ "Client requested: " ++ show question->     answer <- request question->     lift $ putStrLn $ "Client received : " ++ show answer->     lift $ putStrLn "*"--    Again, the type explains what the 'Client' does:-->        | Question | Answer | Base monad | Return value-> Client   Int      | Int    | IO         | ()--    Our 'Client' asks questions about 'Int's and receives answers that are-    'Int's.  The 'Client' also uses 'IO' as the base monad.--    We can then compose the 'Client' and 'Server' into a 'Session' using the-    ('<-<') operator:--> session :: () -> Session IO ()-> session = oneTwoThree <-< incrementer--    The 'Session' type indicates that we have a self-contained session that we-    can run in the 'IO' monad.  We run it using the the 'runProxy' function:-->>> runProxy session :: IO ()-Client requested: 1-Server received : 1-Server responded: 2-Client received : 2-*-Client requested: 2-Server received : 2-Server responded: 3-Client received : 3-*-Client requested: 3-Server received : 3-Server responded: 4-Client received : 4-*--    Now, let's add an intermediate 'Proxy' between the 'Client' and 'Server'-    that subtly tampers with the stream going through it:--> malicious :: Int -> Proxy Int Int Int Int IO r-> malicious question = do->     question' <- if (question > 2)->                  then do->                      lift $ putStrLn "MUAHAHAHA!"->                      return (question + 1)->                  else return question->     answer <- request question'->     nextQuestion <- respond answer->     malicious nextQuestion--    The type tells us what our 'Proxy' does:-->       | Upstream (Server) | Downstream (Client) |->       | Question | Answer | Question |  Answer  | Base monad | Return value-> Proxy   Int        Int      Int         Int       IO           r--    A 'Proxy' bridges two separate interfaces.  The first two parameters define-    the upstream interface (i.e. in the 'Server' direction) and the second two-    parameters define the downstream interface (i.e. in the 'Client' direction).--    We can see if our proxy does its job correctly:-->>> runProxy $ oneTwoThree <-< malicious <-< incrementer-Client requested: 1-Server received : 1-Server responded: 2-Client received : 2-*-Client requested: 2-Server received : 2-Server responded: 3-Client received : 3-*-Client requested: 3-MUAHAHAHA!-Server received : 4-Server responded: 5-Client received : 5-*--    We can also add more proxies as we see fit:-->>> runProxy $ oneTwoThree <-< malicious <-< malicious <-< incrementer -Client requested: 1-Server received : 1-Server responded: 2-Client received : 2-*-Client requested: 2-Server received : 2-Server responded: 3-Client received : 3-*-Client requested: 3-MUAHAHAHA!-MUAHAHAHA!-Server received : 5-Server responded: 6-Client received : 6-*--}--{- $types-    You probably noticed something odd: ('<-<') seems to be composing values of-    different types.  Sometimes it composes a 'Server' or a 'Client' or a-    'Proxy'.  In reality, though, both 'Server' and 'Client' are just type-    synonyms for special cases of 'Proxy':--> type Server arg ret = Proxy C   ()  arg ret-> type Client arg ret = Proxy arg ret ()  C--    A 'Server' is just a 'Proxy' that has no upstream interface, and a 'Client'-    is just a 'Proxy' that has no downstream interface.  In fact, 'Session' is-    also a 'Proxy', one with both ends closed:--> type Session        = Proxy C   ()  ()  C--    The 'Proxy' is the unifying type that all other types derive from and-    ('<-<') always composes two 'Proxy's and returns a new 'Proxy' of the-    correct type.--    You also probably noticed another odd thing: we parametrize every 'Proxy'-    on its initial argument:-->                +- Initial Arg->                |->                v-> incrementer :: Int -> Server         Int Int IO r-> malicious   :: Int -> Proxy  Int Int Int Int IO r-> oneTwoThree :: ()  -> Client Int Int         IO ()->-> session     :: ()  -> Session                IO ()--    This input initializes each 'Proxy' and corresponds to the input on the-    downstream interface.  I will expand the 'Server' and 'Client' type synonyms-    to show this:-->                +- Initial Arg = This -+->                |                      |->                v                      v-> incrementer :: Int -> Proxy  C   ()  Int Int IO r-> malicious   :: Int -> Proxy  Int Int Int Int IO r-> oneTwoThree :: ()  -> Proxy  Int Int ()  C   IO ()->-> session     :: ()  -> Proxy  C   ()  ()  C   IO ()--    Composition supplies the first request through this initial parameter-    and all subsequent requests are bound to 'respond' statements.--    This means that the actual types you compose are all of the form:--> proxy :: req_b -> Proxy req_a resp_a req_b resp_b m r--}--{- $composition-    'Proxy' composition posseses an identity 'Proxy' that is completely-    transparent to anything upstream or downstream of it:--> idT :: (Monad m) => req -> Proxy req resp req resp m r-> idT question = do->     answer       <- request question->     nextQuestion <- respond answer->     idT nextQuestion--    Transparency means that:--> idT <-< p = p->-> p <-< idT = p--    Also, 'Proxy' composition has the nice property that it behaves exactly the-    same way no matter how you group components:--> (p1 <-< p2) <-< p3 = p1 <-< (p2 <-< p3)--    This means that ('<-<') and 'idT' define a category, and the above equations-    are the category laws.  These laws guarantee the following nice-    properties of components:--    * You can reason about each component's behavior independently of other-      components--    * You don't encounter boundary cases between components--    * You don't encounter edge cases at the 'Server' or 'Client' ends--    The semantics of 'Proxy' composition are simple:--    * 'request' blocks until it receives a response from upstream--    * 'respond' blocks until it receives a new request from downstream--    * If any 'Proxy' in the chain terminates, the entire chain terminates--}--{- $idioms-    We frequently encounter the following recurring pattern when writing-    'Proxy's:--> someProxy arg = do->     ...->     nextArg <- respond x->     someProxy nextArg--    "Control.Proxy" provides the 'foreverK' utility function which abstracts-    away this manual recursion:--> foreverK f = f >=> foreverK f--    Using 'foreverK', we can simplify the definition of 'incrementer':--> incrementer = foreverK $ \question -> do->     lift $ putStrLn $ "Server received : " ++ show question->     let answer = question + 1->     lift $ putStrLn $ "Server responded: " ++ show answer->     respond answer--    ... which looks exactly like the way you might write server code in another-    programming language.--    We can similarly simplify 'malicious' this way:--> malicious = foreverK $ \question -> do->     question' <- if (question > 2)->                  then do->                      lift $ putStrLn "MUAHAHAHA!"->                      return (question + 1)->                  else return question->     answer <- request question'->     respond answer--    ... or 'idT':--> idT = foreverK $ \question -> do->     answer <- request question->     respond answer->-> -- or: idT = foreverK (request >=> respond)-> --         = request >=> respond >=> request >=> respond >=> ...--}--{- $reuse-    We can mix and match different components to rapidly define emergent-    behaviors from a resuable set of core primitives.  For example, we could-    replace our client with a command line prompt where the user provides the-    input to the server:--> inputPrompt :: (Read a, Show b) => () -> Client a b IO r-> inputPrompt () = forever $ do->     str <- lift $ getLine->     let a = read str->     b <- request a->     lift $ print b->     lift $ putStrLn "*"-->>> runProxy $ inputPrompt <-< incrementer-42<Enter>-Server received : 42-Server responded: 43-43-*-666<Enter>-Server received : 666-Server responded: 667-667-*--    Oh no, we lost our useful client diagnostic messages!  No worries, we can-    abstract that functionality away into its own component:--> diagnoseClient :: (Show a, Show b) => a -> Proxy a b a b IO r-> diagnoseClient = foreverK $ \a -> do->     lift $ putStrLn $ "Client requested: " ++ show a->     b <- request a->     lift $ putStrLn $ "Client received : " ++ show b->     respond b-->>> runProxy $ inputPrompt <-< diagnoseClient <-< incrementer-42<Enter>-Client requested: 42-Server received : 42-Server responded: 43-Client received : 43-43-*-666<Enter>-Client requested: 666-Server received : 666-Server responded: 667-Client received : 667-667-*--    Because of associativity, we can bundle @inputPrompt@ and @diagnoseClient@-    into a single black box and not worry that the abstraction will leak due to-    grouping issues:--> verboseInput :: (Read a, Show b, Show a) => () -> Client a b IO r-> verboseInput = inputPrompt <-< diagnoseClient-->>> runProxy $ verboseInput <-< incrementer-<Exactly same behavior>--    Or what if I want to cache the results coming out of @incrementer@?  I can-    define a 'Proxy' to cache all requests going through it:--> import qualified Data.Map as M->-> cache :: (Ord a) => a -> Proxy a b a b IO r-> cache = cache' M.empty->-> cache' m a =->     case M.lookup a m of->         Nothing -> do->             b  <- request a->             a' <- respond b->             cache' (M.insert a b m) a'->         Just b  -> do->             lift $ putStrLn "Used cache!"->             a' <- respond b->             cache' m a'-->>> runProxy $ verboseInput <-< cache <-< incrementer -42<Enter>-Client requested: 42-Server received : 42-Server responded: 43-Client received : 43-43-*-42<Enter>-Client requested: 42-Used cache!-Client received : 43-43-*--    Note that I don't distinguish between a \"reverse proxy\" or a \"forward-    proxy\" since composition doesn't distinguish either.  You can attach the-    @cache@ 'Proxy' to a 'Client':--> client' = client <-< cache--    ... or to a 'Server':--> server' = cache <-< server--    ... or anywhere in between.  It's completely up to you!--}--{- $monads-    All the previous examples use a single composition chain, but you need not-    restrict yourself to that design pattern.  Remember that the result of-    composition is a 'Proxy' itself (parametrized by an input), and 'Proxy's are-    'Monad's, so you can bind the result of composition directly within another-    @do@ block to generate complex behaviors:--> mixedClient :: () -> Client Int Int IO r-> mixedClient () = do->     oneTwoThree ()->     -- Here we bind composition within a larger do block->     (inputPrompt <-< cache) ()->-> -- or: mixedClient = oneTwoThree >=> (inputPrompt <-< cache)-->>> runProxy $ mixedClient <-< incrementer-Client requested: 1-Server received : 1-Server responded: 2-Client received : 2-*-Client requested: 2-Server received : 2-Server responded: 3-Client received : 3-*-Client requested: 3-Server received : 3-Server responded: 4-Client received : 4-*-42<Enter>-Server received : 42-Server responded: 43-43-*-42<Enter>-Used cache!-43-*--    So feel free to use your imagination!  Up until the moment you call-    'runProxy', you can freely mix composition or @do@ notation within each-    other.--}--{- $utility-    This library features several utility proxies to get you started.  They all-    reside under the "Control.Proxy.Prelude" hierarchy and they are imported by-    default when you import "Control.Proxy".--    For example, if you wanted to print the first 3 natural numbers, you would-    use:-->>> runProxy $ printD <-< enumFromToS 1 3-1-2-3--    The utility functions follow a systematic naming convention that uses the-    last letter:--    * @D@: Only interacts with values going \'@D@\'ownstream towards the-      'Client'--    * @U@: Only interacts with values going \'@U@\'pstream towards the 'Server'--    * @B@: Interacts with values going \'@B@\'oth ways--    * @C@: Belongs in the \'@C@\'lient position--    * @S@: Belongs in the \'@S@\'server position--    Many utility proxies auto-forward values they receive, such as 'printD'.-    This means we can easily combine multiple handling stages for processing-    values:--> import Control.Proxy-> import System.IO->-> main = do->    h <- openFile "test.txt" WriteMode->    runProxy $ hPrintD h <-< printD <-< enumFromToS 1 3->    hClose h-->>> main-1-2-3--    The above program also wrote the same output to the file "test.txt":--> $ cat test.txt-> 1-> 2-> 3--    'runProxy' discards any output that goes past the endpoints of the session,-    so you don't need to worry about closing off each end.--    This library does not provide 'ByteString' or 'Text' utilities in order to-    reduce the number of dependencies of the main package.  These will be-    released in a separate package in the near future.--}--{- $pipes-    'Proxy's generalize 'Pipe's by permitting communication upstream.-    Fortunately, though, you don't need to rewrite your code if you have already-    used 'Pipe's.  "Control.Proxy" formulates all of the 'Pipe' types and-    primitives in terms of the 'Proxy' type.--    This means that if you wish to upgrade your 'Pipe' code to take advantage of-    upstream communication, you only need to import "Control.Proxy" instead-    of "Control.Pipe" and everything will still work out of the box.  Then you-    can selectively upgrade certain components to communicate upstream as-    necessary.--    To understand how 'Pipe's map onto 'Proxy's, just check out the 'Pipe'-    definition in "Control.Proxy.Pipe":--> type Pipe a b = Proxy () a () b--    In other words, a 'Pipe' is just a 'Proxy' where you never pass any-    information upstream.+{-| This module provides a brief introductory tutorial in the \"Introduction\"+    section followed by a lengthy discussion of the library's design and idioms.+-}++module Control.Proxy.Tutorial (+    -- * Introduction+    -- $intro++    -- * Bidirectionality+    -- $bidir++    -- * Type Synonyms+    -- $synonyms++    -- * Request and Respond+    -- $interact++    -- * Composition+    -- $composition++    -- * The Proxy Class+    -- $class++    -- * Interleaving Effects+    -- $interleave++    -- * Mixing Base Monads+    -- $hoist++    -- * Utilities+    -- $utilities++    -- * Mix Monads and Composition+    -- $mixmonadcomp++    -- * Folds+    -- $folds++    -- * Resource Management+    -- $resource++    -- * Extensions+    -- $extend++    -- * Error handling+    -- $error++    -- * Local state+    -- $state++    -- * Branching, zips, and merges+    -- $branch++    -- * Proxy Transformers+    -- $proxytrans++    -- * Conclusion+    -- $conclusion+    ) where++-- For documentation+import Control.Category+import Control.Monad.Trans.Class+import Control.MFunctor+import Control.PFunctor+import Control.Proxy+import Control.Proxy.Core.Correct (ProxyCorrect)+import Control.Proxy.Trans.Either+import Prelude hiding (catch)++{- $intro+    The @pipes@ library replaces lazy 'IO' with a safe, elegant, and+    theoretically principled alternative.  Use this library if you:++    * want to write high-performance streaming programs++    * believe that lazy 'IO' was a bad idea++    * enjoy composing modular and reusable components++    * love theory and elegant code++    This library unifies many kinds of streaming abstractions, all of which are+    special cases of \"proxies\" (The @pipes@ name is a legacy of one such+    abstraction).++    Let's begin with the simplest 'Proxy': a 'Producer'.  The following+    'Producer' lazily streams lines from a 'Handle'++> import Control.Monad+> import Control.Proxy+> import System.IO+> +> --                Produces Strings ---+----------++> --                                    |          |+> --                                    v          v+> lines' :: (Proxy p) => Handle -> () -> Producer p String IO r+> lines' h () = runIdentityP loop where+>     loop = do+>         eof <- lift $ hIsEOF h+>         if eof+>         then return ()+>         else do+>             str <- lift $ hGetLine h+>             respond str  -- Produce the string+>             loop+>+> -- Ignore the 'runIdentityP' and '()' for now++    But why limit ourselves to streaming lines from some file?  Why not lazily+    generate values from an industrious user?++> --               Uses 'IO' as the base monad --++> --                                             |+> --                                             v+> promptInt :: (Proxy p) => () -> Producer p Int IO r+> promptInt () = runIdentityP $ forever $ do+>     lift $ putStrLn "Enter an Integer:"+>     n <- lift readLn  -- 'lift' invokes an action in the base monad+>     respond n++    Now we need to hook our 'Producer's up to a 'Consumer'.  The following+    'Consumer' endlessly 'request's a stream of 'Show'able values and 'print's+    them:++> --                   Consumes 'a's ---+----------+    +-- Never terminates, so+> --                                    |          |    |   the return value is+> --                                    v          v    v   polymorphic+> printer :: (Proxy p, Show a) => () -> Consumer p a IO r+> printer () = runIdentityP $ forever $ do+>     a <- request ()  -- Consume a value+>     lift $ putStrLn "Received a value:"+>     lift $ print a++    You can compose a 'Producer' and a 'Consumer' using ('>->'), which produces+    a runnable 'Session':++> --                Self-contained session ---+         +--+-- These must match+> --                                          |         |  |   each component+> --                                          v         v  v+> promptInt >-> printer :: (Proxy p) => () -> Session p IO r+>+> lines' h  >-> printer :: (Proxy p) => () -> Session p IO ()++    ('>->') connects each 'request' in @printer@ with a 'respond' in+    @lines'@ or @promptInt@.++    Finally, you use 'runProxy' to run the 'Session' and convert it back to the+    base monad.  First we'll try our @lines'@ 'Producer', which will stream+    lines from the following file:++> $ cat test.txt+> Line 1+> Line 2+> Line 3++    The following program never brings more than a single line into memory (not+    that it matters for such a small file):++>>> withFile "test.txt" $ \h -> runProxy $ lines' h >-> printer+Received a value:+"Line 1"+Received a value:+"Line 2"+Received a value:+"Line 3"++    Similarly, we can lazily stream user input, requesting values from the user+    only when we need them:++>>> runProxy $ promptInt >-> printer :: IO r+Enter an Integer:+1<Enter>+Received a value:+1+Enter an Integer:+5<Enter>+Received a value:+5+...++    The last example proceeds endlessly until we hit @Ctrl-C@ to interrupt it.++    We would like to limit the number of iterations, so lets define an+    intermediate 'Proxy' that behaves like a verbose 'take'.  I will call it a+    'Pipe' (this library's namesake) since values flow through it:++>                           'a's flow in ---+ +--- 'a's flow out+>                                           | |+>                                           v v+> take' :: (Proxy p) => Int -> () -> Pipe p a a IO ()+> take' n () = runIdentityP $ do+>     replicateM_ n $ do+>         a <- request ()+>         respond a+>     lift $ putStrLn "You shall not pass!"++    This 'Pipe' forwards the first @n@ values it receives undisturbed, then it+    outputs a cute message.  You can compose it between the 'Producer' and+    'Consumer' using ('>->'):++>>> runProxy $ promptInt >-> take' 2 >-> printer :: IO ()+Enter an Integer:+9<Enter>+Received a value:+9+Enter an Integer:+2<Enter>+Received a value:+2+You shall not pass!++    When @take' 2@ terminates, it brings down every 'Proxy' composed with it.++    Notice how @promptInt@ behaves lazily and only 'respond's with as many+    values as we 'request'.  We 'request'ed exactly two values, so it only+    prompts the user twice.++    We can already spot several improvements upon traditional lazy 'IO':++    * You can define your own lazy components that have nothing to do with files++    * @pipes@ never uses 'unsafePerformIO' or violates referential transparency.++    * You don't need strictness hacks to ensure the proper ordering of effects++    * You can interleave effects in downstream stages, too++    However, this library can offer even more than that!+-}++{- $bidir+    So far we've only defined proxies that send information downstream in the+    direction of the ('>->') arrow.  However, we don't need to limit ourselves+    to unidirectional communication and we can enhance these proxies with the+    ability to send information upstream with each 'request' that determines+    how upstream stages 'respond'.++    For example, 'Client's generalize 'Consumer's because they can supply an+    argument other than @()@ with each 'request'.  The following 'Client'+    sends three 'request's upstream, each of which provides an 'Int' @argument@+    and expects a 'Bool' @result@:++>                      Sends out 'Int's ---+   +-- Receives back 'Bool's+>                                          |   |+>                                          v   v+> threeReqs :: (Proxy p) => () -> Client p Int Bool IO ()+> threeReqs () = runIdentityP $ forM_ [1, 3, 1] $ \argument -> do+>     lift $ putStrLn $ "Client Sends:   " ++ show (argument :: Int)+>     result <- request argument+>     lift $ putStrLn $ "Client Receives:" ++ show (result :: Bool)+>     lift $ putStrLn "*"++    Notice how 'Client's use \"@request argument@\" instead of+    \"@request ()@\".  This sends \"@argument@\" upstream to parametrize the+    'request'.++    'Server's similarly generalize 'Producer's because they receive arguments+    other than @()@.  The following 'Server' receives 'Int' 'request's and+    'respond's with 'Bool' values:++>                       Receives 'Int's ---+   +--- Replies with 'Bool's+>                                          |   |+>                                          v   v+> comparer :: (Proxy p) => Int -> Server p Int Bool IO r+> comparer = runIdentityK loop where+>     loop argument = do+>         lift $ putStrLn $ "Server Receives:" ++ show (argument :: Int)+>         let result = argument > 2+>         lift $ putStrLn $ "Server Sends:   " ++ show (result :: Bool)+>         nextArgument <- respond result+>         loop nextArgument++    Notice how 'Server's receive their first argument as a parameter and bind+    each subsequent argument using 'respond'.  This library provides a+    combinator which abstracts away this common pattern:++> foreverK :: (Monad m) => (a -> m a) -> a -> m b+> foreverK f = loop where+>     loop argument = do+>          nextArgument <- f argument+>          loop nextArgument+>+> -- or: foreverK f = f >=> foreverK f+> --                = f >=> f >=> f >=> f >=> ...++    We can use this to simplify the @comparer@ 'Server':++> comparer = runIdentityK $ foreverK $ \argument -> do+>     lift $ putStrLn $ "Server Receives:" ++ show argument+>     let result = argument > 2+>     lift $ putStrLn $ "Server Sends:   " ++ show result+>     respond result++    ... which looks just like the way you might write a server's main loop in+    another programming language.++    You can compose a 'Server' and 'Client' using ('>->'), and this also returns+    a runnable 'Session':++> comparer >-> threeReqs :: (Proxy p) => () -> Session p IO ()++    Running this executes the client-server session:++>>> runProxy $ comparer >-> threeReqs :: IO ()+Client Sends:    1+Server Receives: 1+Server Sends:    False+Client Receives: False+*+Client Sends:    3+Server Receives: 3+Server Sends:    True+Client Receives: True+*+Client Sends:    1+Server Receives: 1+Server Sends:    False+Client Receives: False+*++    'Proxy's generalize 'Pipe's because they allow information to flow upstream.+    The following 'Proxy' caches 'request's to reduce the load on the 'Server'+    if the request matches a previous one:++> import qualified Data.Map as M+>+> -- 'p' is the Proxy, as the (Proxy p) constraint indicates+>+> cache :: (Proxy p, Ord key) => key -> p key val key val IO r+> cache = runIdentityK (loop M.empty) where+>     loop _map key = case M.lookup key _map of+>         Nothing -> do+>             val  <- request key+>             key2 <- respond val+>             loop (M.insert key val _map) key2+>         Just val -> do+>             lift $ putStrLn "Used cache!"+>             key2 <- respond val+>             loop _map key2++    You can compose the @cache@ 'Proxy' between the 'Server' and 'Client' using+    ('>->'):++>>> runProxy $ comparer >-> cache >-> threeReqs+Client Sends:    1+Server Receives: 1+Server Sends:    False+Client Receives: False+*+Client Sends:    3+Server Receives: 3+Server Sends:    True+Client Receives: True+*+Client Sends:    1+Used cache!+Client Receives: False+*++    This bidirectional flow of information separates @pipes@ from other+    streaming libraries which are unable to model 'Client's, 'Server's, or+    'Proxy's.  Using @pipes@ you can define interfaces to RPC interfaces, REST+    architectures, message buses, chat clients, web servers, network protocols+    ... you name it!+-}++{- $synonyms+    You might wonder why ('>->') accepts 'Producer's, 'Consumer's, 'Pipe's,+    'Client's, 'Server's, and 'Proxy's.  It turns out that these type-check+    because they are all type synonyms that expand to the following central+    type:++> (Proxy p) => p a' a b' b m r++    Like the name suggests, a 'Proxy' exposes two interfaces: an upstream+    interface and a downstream interface.  Each interface can both send and+    receive values:++> Upstream | Downstream+>     +---------++>     |         |+> a' <==       <== b'+>     |  Proxy  |+> a  ==>       ==> b+>     |         |+>     +---------+++    Proxies are monad transformers that enrich the base monad with the ability+    to send or receive values upstream or downstream:++>   | Sends    | Receives | Receives   | Sends      | Base  | Return+>   | Upstream | Upstream | Downstream | Downstream | Monad | Value+> p   a'         a          b'           b            m       r++    We can selectively close certain inputs or outputs to generate specialized+    proxies.++    For example, a 'Producer' is a 'Proxy' that can only output values to its+    downstream interface:++> Upstream | Downstream+>     +----------++>     |          |+> C  <==        <== ()+>     | Producer |+> () ==>        ==> b+>     |          |+>     +----------++>+> type Producer p b m r = p C () () b m r+>+> -- The 'C' type is uninhabited, so it 'C'loses an output end++    A 'Consumer' is a 'Proxy' that can only receive values on its upstream+    interface:++> Upstream | Downstream+>     +----------++>     |          |+> () <==        <== ()+>     | Consumer |+> a  ==>        ==> C+>     |          |+>     +----------++>+> type Consumer p a m r = p () a () C m r++    A 'Pipe' is a 'Proxy' that can only receive values on its upstream interface+    and send values on its downstream interface:++> Upstream | Downstream+>     +--------++>     |        |+> () <==      <== ()+>     |  Pipe  |+> a  ==>      ==> b+>     |        |+>     +--------++>+> type Pipe p a b m r = p () a () b m r++    When we compose proxies, the type system ensures sure that their input and+    output types match:++>       promptInt    >->    take' 2    >->    printer+>+>     +-----------+       +---------+       +---------++>     |           |       |         |       |         |+> C  <==         <== ()  <==       <== ()  <==       <== ()+>     |           |       |         |       |         |+>     | promptInt |       | take' 2 |       | printer |+>     |           |       |         |       |         |+> () ==>         ==> Int ==>       ==> Int ==>       ==> C+>     |           |       |         |       |         |+>     +-----------+       +---------+       +---------+++    Composition fuses these into a new 'Proxy' that has both ends closed, which+    is a 'Session':++>     +-----------------------------------++>     |                                   |+> C  <==                                 <== ()+>     |                                   |+>     | promptInt >-> take' 2 >-> printer |+>     |                                   |+> () ==>                                 ==> C+>     |                                   |+>     +-----------------------------------++>+> type Session p m r = p C () () C m r++    A 'Client' is a 'Proxy' that only uses its upstream interface:++> Upstream | Downstream+>     +----------++>     |          |+> a' <==        <== ()+>     |  Client  |+> a  ==>        ==> C+>     |          |+>     +----------++>+> type Client p a' a m r = p a' a () C m r++    A 'Server' is a 'Proxy' that only uses its downstream interface:+++> Upstream | Downstream+>     +----------++>     |          |+> C  <==        <== b'+>     |  Server  |+> () ==>        ==> b+>     |          |+>     +----------++>+> type Server p b' b m r = p C () b' b m r++    The compiler ensures that the types match when we compose 'Server's,+    'Proxy's, and 'Client's.++>        comparer   >->     cache   >->      threeReqs+>+>     +----------+        +-------+        +-----------++>     |          |        |       |        |           |+> C  <==        <== Int  <==     <== Int  <==         <== ()+>     |          |        |       |        |           |+>     | comparer |        | cache |        | threeReqs |+>     |          |        |       |        |           |+> () ==>        ==> Bool ==>     ==> Bool ==>         ==> C+>     |          |        |       |        |           |+>     +----------+        +-------+        +-----------+++    This similarly fuses into a 'Session':++>     +----------------------------------++>     |                                  |+> C  <==                                <== ()+>     |                                  |+>     | comparer >-> cache >-> threeReqs |+>     |                                  |+> () ==>                                ==> C+>     |                                  |+>     +----------------------------------+++    @pipes@ encourages substantial code reuse by implementing all abstractions+    as type synonyms on top of a single type class: 'Proxy'.  This makes your+    life easier because:++    * You only use one composition operator: ('>->')++    * You can mix multiple abstractions together as long as the types match+-}++{- $interact+    There are only two ways to interact with other proxies: 'request' and+    'respond'.  Let's examine their type signatures to understand how they+    work:++> request :: (Monad m, Proxy p) => a' -> p a' a b' b m a+>                                  ^                   ^+>                                  |                   |+>                       Argument --+          Result --+++    'request' sends an argument of type @a'@ upstream, and binds a result of+    type @a@.  Whenever you 'request', you block until upstream 'respond's with+    a value.+++> respond :: (Monad m, Proxy p) => b -> p a' a b' b m b'+>                                  ^                  ^+>                                  |                  |+>                         Result --+  Next Argument --+++    'respond' replies with a result of type @b@, and then binds the /next/+    argument of type @b'@.  Whenever you 'respond', you block until downstream+    'request's a new value.++    Wait, if 'respond' always binds the /next/ argument, where does the /first/+    argument come from?  Well, it turns out that every 'Proxy' receives this+    initial argument as an ordinary parameter, as if they all began blocked on+    a 'respond' statement.+   +    We can see this if we take all the previous proxies we defined and fully+    expand every type synonym.  The initial argument of each 'Proxy' matches+    the type parameter corresponding to the return value of 'respond':++>                                          These+>                                    +--  Columns  ---++>                                    |     Match      |+>                                    v                v+> promptInt :: (Proxy p)          => ()  -> p C   ()  ()  Int  IO r+> printer   :: (Proxy p, Show a)  => ()  -> p ()  a   ()  C    IO r+> take'     :: (Proxy p)   => Int -> ()  -> p ()  a   ()  a    IO ()+> comparer  :: (Proxy p)          => Int -> p C   ()  Int Bool IO r+> cache     :: (Proxy p, Ord key) => key -> p key val key val  IO r++    You can also study the type of composition, which follows this same pattern.+    Composition requires two 'Proxy's blocked on a 'respond', and produces a new+    'Proxy' similarly blocked on a 'respond':++> (>->) :: (Monad m, Proxy p)+>  => (b' -> p a' a b' b m r)+>  -> (c' -> p b' b c' c m r)+>  -> (c' -> p a' a c' c m r)+>      ^            ^+>      |   These    |+>      +---Match----+++    This is why 'Producer's, 'Consumer's, and 'Client's all take @()@ as their+    initial argument, because their corresponding 'respond' commands all have a+    return value of @()@.++    This library also provides ('>~>'), which is the dual of the ('>->')+    composition operator.  ('>~>') composes two 'Proxy's blocked on a 'request'+    and returns a new 'Proxy' blocked on a 'request':++> (>~>)+>  :: (Monad m, Proxy p)+>  => (a -> p a' a b' b m r)+>  -> (b -> p b' b c' c m r)+>  -> (a -> p a' a c' c m r)++    Conceptually, ('>->') composes pull-based systems and ('>~>') composes+    push-based systems.++    In fact, if you went back through the previous code and systematically+    replaced every:++    * ('>->') with ('>~>'),++    * 'respond' with 'request', and++    * 'request' with 'respond'++    ... then everything would still work and produce identical behavior, except+    the compiler would now infer the symmetric types with all interfaces+    reversed.  We can therefore conclude the obvious: pull-based systems are+    symmetric to push-based systems.++    Since these two composition operators are perfectly symmetric, I arbitrarily+    standardize on using ('>->') and I provide all standard library proxies+    blocked on 'respond' so that they work with ('>->').  This gives behavior+    more familiar to Haskell programmers that work with lazy pull-based+    functions.  I only include the ('>~>') composition operator for theoretical+    completeness.+-}++{- $composition+    When we compose @(p1 >-> p2)@, composition ensures that @p1@'s downstream+    interface matches @p2@'s upstream interface.  This follows from the type of+    ('>->'):++> (>->) :: (Monad m, Proxy p)+>  => (b' -> p a' a b' b m r)+>  -> (c' -> p b' b c' c m r)+>  -> (c' -> p a' a c' c m r)++    Diagramatically, this looks like:++>         p1     >->      p2+>+>     +--------+      +--------++>     |        |      |        |+> a' <==      <== b' <==      <== c'+>     |   p1   |      |   p2   |+> a  ==>      ==> b  ==>      ==> c+>     |        |      |        |+>     +--------+      +--------+++    @p1@'s downstream @(b', b)@ interface matches @p2@'s upstream @(b', b)@+    interface, so composition connects them on this shared interface.  This+    fuses away the @(b', b)@ interface, leaving behind @p1@'s upstream @(a', a)@+    interface and @p2@'s downstream @(c', c)@ interface:++>     +-----------------++>     |                 |+> a' <==               <== c'+>     |   p1  >->  p2   |+> a  ==>               ==> c+>     |                 |+>     +-----------------+++    Proxy composition has the very nice property that it is associative, meaning+    that it behaves the exact same way no matter how you group composition:++> (p1 >-> p2) >-> p3 = p1 >-> (p2 >-> p3)++    ... so you can safely elide the parentheses:++> p1 >-> p2 >-> p3++    Also, we can define a \'@T@\'ransparent 'Proxy' that auto-forwards values+    both ways:++> idT :: (Monad m, Proxy p) => a' -> p a' a a' a m r+> idT = runIdentityK loop where+>     loop a' = do+>         a   <- request a'+>         a'2 <- respond a+>         loop a'2+>+> -- or: idT = runIdentityK $ foreverK $ request >=> respond+> --         = runIdentityK $ request >=> respond >=> request >=> respond ...++    Diagramatically, this looks like:++>     +-----++>     |     |+> a' <======== a'   <- All values pass+>     | idT |          straight through+> a  ========> a    <- immediately+>     |     |+>     +-----+++    Transparency means that:++> idT >-> p = p+>+> p >-> idT = p++    In other words, 'idT' is an identity of composition.++    This means that proxies form a true 'Category' where ('>->') is composition+    and 'idT' is the identity.   The associativity law and the two+    identity laws are just the 'Category' laws.  The objects of the category are+    the 'Proxy' interfaces.++    These 'Category' laws guarantee the following important properties:++    * You can reason about each proxy's behavior independently of other proxies++    * You don't encounter weird behavior at the interface between two components++    * You don't encounter corner cases at the 'Server' or 'Client' ends of a+     'Session'+-}++{- $class+    All the proxy code we wrote was generic over the 'Proxy' type class, which+    defines the three central operations of this library's API:++    * ('>->'): Proxy composition++    * 'request': Request input from upstream++    * 'respond': Respond with output to downstream++    @pipes@ defines everything in terms of these three operations, which is+    why all the library's utilities are polymorphic over the 'Proxy' type class.++    Let's look at some example instances of the 'Proxy' type class:++> instance Proxy ProxyFast     -- Fastest implementation+> instance Proxy ProxyCorrect  -- Strict monad transformer laws++    These two types provide the two alternative base implementations:++    * 'ProxyFast': This runs significantly faster on pure code segments and+      employs several rewrite rules to optimize your code into the equivalent+      hand-tuned code.++    * 'ProxyCorrect': This uses a monad transformer implementation that is+      correct by construction, but runs about 8x slower on pure code segments.+      However, for 'IO'-bound code, the performance gap is small.++    These two implementations differ only in the 'runProxy' function that they+    export, which is how the compiler selects which 'Proxy' implementation to+    use.++    "Control.Proxy" automatically selects the fast implementation for you, but+    you can always choose the correct implementation instead by replacing+    "Control.Proxy" with the following two imports:++> import Control.Proxy.Core         -- Everything except the base implementation+> import Control.Proxy.Core.Correct -- The alternative base implementation++    These are not the only instances of the 'Proxy' type class!  This library+    also provides several \"proxy transformers\", which are like monad+    transformers except that they also correctly lift the 'Proxy' type class:++> instance (Proxy p) => Proxy (IdentityP p)+> instance (Proxy p) => Proxy (EitherP e p)+> instance (Proxy p) => Proxy (MaybeP    p)+> instance (Proxy p) => Proxy (ReaderP i p)+> instance (Proxy p) => Proxy (StateP  s p)+> instance (Proxy p) => Proxy (WriterP w p)++    All of the 'Proxy' code we wrote so far also works seamlessly with all of+    these proxy transformers.  The 'Proxy' class abstracts over the+    implementation details and extensions so that you can reuse the same library+    code for any feature set.++    This polymorphism comes at a price: you must embed your 'Proxy' code in at+    least one proxy transformer if you want clean type class constraints.  If+    you don't use extensions then you embed your code in the identity proxy+    transformer: 'IdentityP'.  This is why all the examples use 'runIdentityP'+    or 'runIdentityK' to embed their code in 'IdentityP'.  "Control.Proxy.Class"+    provides a longer discussion on this subject.++    Without this 'IdentityP' embedding, the compiler infers uglier constraints,+    which are also significantly less polymorphic.  We can show this by+    removing the 'runIdentityP' call from @promptInt@ and see what type the+    compiler infers:++> promptInt () = forever $ do+>     lift $ putStrLn "Enter an Integer:"+>     n <- lift readLn+>     respond n++>>> :t promptInt -- I've substantially cleaned up the inferred type+promptInt+  :: (Monad (Producer p Int IO), MonadTrans (Producer p Int), Proxy p) =>+     () -> Producer p Int IO r++    All 'Proxy' instances are already monads and monad transformers, but the+    compiler cannot infer that without the 'IdentityP' embedding.  When we embed+    @promptInt@ in 'IdentityP', the compiler collapses the 'Monad' and+    'MonadTrans' constraints into the 'Proxy' constraint.++    Fortunately, you do not pay any performance price for this 'IdentityP'+    embedding or the type class polymorphism.  Your polymorphic code will still+    run very rapidly, as fast as if you had specialized it to a concrete+    'Proxy' instance without the 'IdentityP' embedding.  I've taken great care+    to ensure that all optimizations and rewrite rules always see through these+    abstractions without any assistance on your part.+-}++{- $interleave+    When you compose two proxies, you interleave their effects in the base+    monad.  The following two proxies demonstrate this interleaving of effects:++> downstream :: (Proxy p) => Consumer p () IO ()+> downstream () = runIdentityP $ do+>     lift $ print 1+>     request ()  -- Switch to upstream+>     lift $ print 3+>     request ()  -- Switch to upstream+>+> upstream :: (Proxy p) => Producer p () IO ()+> upstream () = runIdentityP $ do+>     lift $ print 2+>     respond () -- Switch to downstraem+>     lift $ print 4++     "Control.Proxy.Class" enumerates the 'Proxy' laws, which equationally+     define how all 'Proxy' instances must behave.  These laws require that+     @(upstream >-> downstream)@ must reduce to the following:++> upstream >-> downstream  -- This is true no matter what feature+> =                        -- set or 'Proxy' instance you select+> \() -> lift $ do+>     print 1+>     print 2+>     print 3+>     print 4++    Conceptually, 'runProxy' just applies this to @()@ and removes the 'lift':++> runProxy $ upstream >-> downstream+> =+> do print 1+>    print 2+>    print 3+>    print 4++    Let's test this:++>>> runProxy $ upstream >-> downstream+1+2+3+4++    The 'Proxy' laws let you reason about how proxies interleave effects without+    knowing any specifics about the underlying implementation.  Intuitively, the+    'Proxy' laws say that:++    * 'request' blocks until upstream 'respond's++    * 'respond' blocks until downstream 'request's++    * If a 'Proxy' terminates, it terminates every 'Proxy' composed with it++    Several of the utilities in "Control.Proxy.Prelude.Base" use these+    equational laws to rigorously prove things about their behavior.  For+    example, consider the 'mapD' proxy, which applies a function @f@ to all+    values flowing downstream:++> mapD :: (Monad m, Proxy p) => (a -> b) -> x -> p x a x b m r+> mapD f = runIdentityK loop where+>     loop x = do+>         a  <- request x+>         x2 <- respond (f a)+>         loop x2+>+> -- or: mapD f = runIdentityK $ foreverK $ request >=> respond . f++    We can use the 'Proxy' laws to prove that:++> mapD f >-> mapD g = mapD (g . f)+>+> mapD id = idT++    ... which is what we expect.  We can fuse two consecutive 'mapD's into one+    by composing their functions, and mapping 'id' does nothing at all, just+    like the identity proxy: 'idT'.++    In fact, these are just the functor laws in disguise, where 'mapD' defines a+    functor between the category of Haskell function composition and the+    category of 'Proxy' composition.  "Control.Proxy.Prelude.Base" is full of+    utilities like this that are simultaneously practical and theoretically+    elegant.+-}++{- $hoist+    Composition can't interleave two proxies if their base monads do not+    match.  For instance, I might try to modify @promptInt@ to use+    @EitherT String@ to report the error instead of using exceptions:++> import Control.Monad.Trans.Either -- from the "either" package+> import Safe (readMay)+>+> promptInt2 :: (Proxy p) => () -> Producer p Int (EitherT String IO) r+> promptInt2 () = runIdentityP $ forever $ do+>     str <- lift $ lift $ do+>         putStrLn "Enter an Integer:"+>         getLine+>     case readMay str of+>         Nothing -> lift $ left "Could not read Integer"+>         Just n  -> respond n++    However, if I try to compose it with @printer@, I receive a type error:++>>> runEitherT $ runProxy $ promptInt2 >-> printer+<interactive>:2:40:+    Couldn't match expected type `EitherT String IO'+                with actual type `IO'+    ...++    The type error says that @promptInt2@ uses @(EitherT String IO)@ for its+    base monad, but @printer@ uses 'IO' for its base monad, so composition can't+    interleave their effects.++    You can easily fix this using the 'hoist' function from the 'MFunctor' type+    class in "Control.MFunctor", which transforms the base monad of any monad+    transformer, including the 'Proxy' monad transformer.  "Control.MFunctor"+    really belongs in the @transformers@ package, however it currently resides+    here because it requires the @Rank2Types@ extension.++    You will commonly use 'hoist' to 'lift' one proxy's base monad to match+    another proxy's base monad, like so:++>>> runEitherT $ runProxy $ promptInt2 >-> (hoist lift . printer)+Enter an Integer:+Hello<Enter>+Left "Could not read Integer"++    This library provides three syntactic conveniences for making this easier to+    write.++    First, ('.') has higher precedence than ('>->'), so you can drop the+    parentheses:++>>> runEitherT $ runProxy $ promptInt2 >-> hoist lift . printer+...++    Second, "lift" is such a common argument to 'hoist' that "Control.MFunctor"+    provides the 'raise' function:++> raise = hoist lift++>>> runEitherT $ runProxy $ promptInt2 >-> raise . printer+...++    Third, "Control.Proxy.Prelude.Kleisli" provides the 'hoistK' and 'raiseK'+    functions in case you think composition looks ugly:++> hoistK f = (hoist f .)+>+> raiseK = (raise .)++>>> runEitherT $ runProxy $ promptInt2 >-> raiseK printer+...++    Note that "Control.MFunctor" also provides 'MFunctor' instances for all the+    monad transformers in the @transformers@ package.  This means that you can+    fix any incompatibility between two monad transformer stacks just using+    various combinations of 'hoist' and 'lift'.++    To see how, consider the following contrived pathological example where I+    want to mix two very different monad transformer stacks:++> m1 :: StateT s (ReaderT i IO) r+> m2 :: MaybeT   (WriterT w IO) r++    I can interleave their transformers through judicious use of 'hoist' and+    'lift'++> mBoth :: StateT s (MaybeT (ReaderT i (WriterT w IO))) r+> mBoth = do+>     hoist (lift . hoist lift) m1+>     lift (hoist lift m2)+-}++{- $utilities+    The "Control.Proxy.Prelude" heirarchy provides several utility functions+    for common tasks.  We can redefine the previous example functions just by+    composing these utilities.++    For example, 'readLnS' reads values from user input, so we can read 'Int's+    just by specializing its type:++> readLnS :: (Proxy p, Read a) => () -> Producer p a IO r+>+> readIntS :: (Proxy p) => () -> Producer p Int IO r+> readIntS = readLnS++    The @S@ suffix indicates that it belongs in the \'@S@\'erver position.++    @(takeB_ n)@ allows at most @n@ value to pass through it in \'@B@\'oth+    directions:++> takeB_ :: (Monad m, Proxy p) => Int -> a' -> p a' a a' a m ()++    'takeB_' has a more general type than @take'@ because it allows any type of+    value to flow upstream.++     'printD' prints all values flowing \'@D@\'ownstream:++> printD :: (Proxy p, Show a) => x -> p x a x a IO r++    'printD' has a more general type than our original @printer@ because it+    forwards all values further downstream after 'print'ing them.  This means+    that you could use it as an intermediate stage as well.  However, 'printD'+    still type-checks as the most downstream stage, too, since 'runProxy' just+    discards any unused outbound values.++    These utilities do not clash with the Prelude namespace or common libraries+    because they all end with a capital letter suffix that indicates their+    directionality:++    * \'@D@\' suffix: interacts with values flowing \'@D@\'ownstream++    * \'@U@\' suffix: interacts with values flowing \'@U@\'pstream++    * \'@B@\' suffix: interacts with values flowing \'@B@\'oth ways (or:+      \'@B@\'idirectional)++    * \'@S@\' suffix: belongs furthest upstream in the \'@S@\'erver position++    * \'@C@\' suffix: belongs furthest downstream in the \'@C@\'lient position++    We can assemble these functions into a silent version of our previous+    'Session':++>>> runProxy $ readIntS >-> takeB_ 2 >-> printD+4<Enter>+4+39<Enter>+39++    Fortunately, we don't have to give up our previous useful diagnostics.+    We can use 'execU', which executes an action each time values flow upstream+    through it, and 'execD', which executes an action each time values flow+    downstream through it:++> promptInt :: (Proxy p) => () -> Producer p Int IO r+> promptInt = readLnS >-> execU (putStrLn "Enter an Integer:")+>+> printer :: (Proxy p, Show a) => x -> p x a x a IO r+> printer = execD (putStrLn "Received a value:") >-> printD++    Similarly, we can build our old @take'@ on top of 'takeB_':++> take' :: (Proxy p) => Int -> a' -> p a' a a' a m ()+> take' n a' = runIdentityP $ do  -- Remember, we need 'runIdentityP' if+>     takeB_ n a'                 -- we use 'do' notation or 'lift'+>     lift $ putStrLn "You shall not pass!"++>>> runProxy $ promptInt >-> take' 2 >-> printer+<Exact same behavior>++    Or perhaps I want to skip user input for testing and mock @promptInt@ by+    replacing it with a predefined set of values:++>>> runProxy $ fromListS [4, 37, 1] >-> take'2 >-> printer+Received a value:+4+Received a value:+37++    What about our original @lines@ function?  That's just 'hGetLineS':++> hGetLineS :: (Proxy p) => Handle -> () -> Producer p String IO ()++    You could hand-write loops that accomplish these same tasks, but proxies let+    you:++    * Rapidly swap in and out components for testing, debugging, and fast+      prototyping++    * Factor out common patterns into modular components++    * Mix and match simple stages to build sophisticated programs++    This compositional programming style emphasizes building a library of+    reusable components and connecting them like Unix pipes to assemble the+    desired streaming program.+-}++{- $mixmonadcomp+    Composition isn't the only way to assemble proxies.  You can also sequence+    predefined proxies using @do@ notation to generate more elaborate behaviors.++    Most commonly, you will sequence two sources to combine their outputs, very+    similar to how the Unix @cat@ utility behaves:++> threeSources () = do+>     source1 ()+>     source2 ()+>     source3 ()+>+> -- or: threeSources = source1 >=> source2 >=> source3++    As a concrete example, we could create a 'Producer' where our first source+    presets the first few values and then we let the user take over to generate+    the remaining values:++> source1 :: (Proxy p) => () -> Producer p Int IO r+> source1 () = runIdentityP $ do+>     fromListS [4, 4] ()  -- Source 1+>     readLnS ()           -- Source 2+>+> -- or: source1 = runIdentityK (fromListS [4, 4] >=> readLnS)++>>> runProxy $ source1 >-> printD+4+4+70<Enter>+70+34<Enter>+34+...++    What if we only want the user to provide three values?  We can +    selectively throttle it with 'takeB_':++> source2 :: (Proxy p) => () -> Producer p Int IO ()+> source2 () = runIdentityP $ do+>     fromListS [4, 4] ()+>     (readLnS >-> takeB_ 3) () -- You can compose inside a do block!+>+> -- or: source2 = runIdentityK (fromListS [4, 4] >=> (readLnS >-> takeB_ 3))++    Notice that composition works inside of a @do@ block!  This is a very handy+    trick!++>>> runProxy $ source2 >-> printD+4+4+56<Enter>+56+41<Enter>+41+80<Enter>+80++    You can also concatenate sinks, too:++> sink1 :: (Proxy p) => () -> Consumer p Int IO ()+> sink1 () = do+>     (takeB_ 3         >-> printD) () -- Sink 1+>     (takeWhileD (< 4) >-> printD) () -- Sink 2+>+> -- or: sink1 = (takeB_ 3 >-> printD) >=> (takeWhileD (< 4) >-> printD)++>>> runProxy $ source2 >-> sink1+4          -- The first sink+4          -- handles these+68<Enter>  --+68+1<Enter>   -- The second sink+1          -- handles these+5<Enter>   --++    ... but the above example is gratuitous because you can simply concatenate+    the intermediate stages:++> sink2 :: (Proxy p) => () -> Consumer p Int IO ()+> sink2 () = intermediate >-> printD where+>     intermediate () = do+>         takeB_ 3 ()       -- Intermediate stage 1+>         takeWhileD (< 4)  -- Intermediate stage 2+>+> -- or: sink2 = (takeB_ 3 >=> takeWhileD (< 4)) >-> printD++>>> runProxy $ source2 >-> sink2+<Exact same behavior>++    These examples demonstrate the two principal ways to combine proxies:++    * \"Vertical\" composition, using ('>=>') from the Kleisli category++    * \"Horizontal\" composition: using ('>->') from the Proxy category++    You assemble most proxies simply by composing them in one or both of these+    two categories.+-}++{- $folds+    You can fold a stream of values in two ways, both of which use the base+    monad:++    * Use 'WriterT' in the base monad and 'tell' the values to fold++    * Use 'StateT' in the base monad and 'put' strict values++    'WriterT' is more elegant in principle but leaks space for a large number of+    values to fold.  'StateT' does not leak space if you keep the accumulator+    strict, but is less elegant and doesn't guarantee write-only behavior.  To+    remedy this, I am currently working on a stricter 'WriterT' implementation+    that does not leak space to add to the @transformers@ package.++    "Control.Proxy.Prelude.Base" provides several common folds using 'WriterT'+    as the base monad, such as:++    * 'lengthD': Count how many values flow downstream++> lengthD :: (Monad m, Proxy p) => x -> p x a x a (WriterT (Sum Int) m) r++    * 'toListD': Fold the values flowing downstream into a list.++> toListD :: (Monad m, Proxy p) => x -> p x a x a (WriterT [a] m) r++    * 'anyD': Determine whether any values satisfy the predicate++> anyD :: (Monad m, Proxy p) => (a -> Bool) -> x -> p x a x a (WriterT Any m) r++    These 'WriterT' versions demonstrate how the elegant approach should work in+    principle and they should be okay for folding a medium number of values+    until I release the fixed 'WriterT'.  If space leaks cause problems, you can+    temporarily rewrite the 'WriterT' folds using the following two strict+    'StateT' folds:++    * 'foldlD'': Strictly fold values flowing downstream++> foldlD'+>  :: (Monad m, Proxy p) => (b -> a -> b) -> x -> p x a x a (StateT b m) r++    * 'foldlU'': Strictly fold values flowing upstream++> foldU'+>  :: (Monad m, Proxy p) => (b -> a' -> b) -> a' -> p a' x a' x (StateT b m) r++    Now, let's try these folds out and see if we can build a list from user+    input:++>>> runWriterT $ runProxy $ raiseK promptInt >-> takeB_ 3 >-> toListD+Enter an Integer:+1<Enter>+Enter an Integer:+66<Enter>+Enter an Integer:+5<Enter>+((), [1, 66, 5])++    Notice that @promptInt@ uses 'IO' as its base monad, but 'toListD' uses+    @(WriterT [Int] m)@ as its base monad, so I use 'raiseK' to get the base+    monads to match.++    You can insert these folds anywhere in the middle of a pipeline and they+    still work:++>>> runWriterT $ runProxy $ fromListS [5, 7, 4] >-> lengthD >-> raiseK printD+5+7+4+((), Sum 3)++    You can also run multiple folds at the same time just by adding more+    'WriterT' layers to your base monad:++>>> runWriterT $ runWriterT $ fromListS [9, 10] >-> anyD even >-> raiseK sumD+(((), Any {getAny = True},Sum {getSum = 19})++    I designed certain special folds to terminate the 'Session' early if they+    can compute their result prematurely, in order to draw as little input as+    possible.  These folds end with an underscore, such as 'headD_', which+    terminates the stream once it receives an input:++> headD_ :: (Monad m, Proxy p) => x -> p x a x a (WriterT (First a) m) ()++>>> runWriterT $ runProxy $ fromListS [3, 4, 9] >-> raiseK printD >-> headD_+3+((), First {getFirst = Just 3})++    Compare this to 'headD' without underscore, which folds the entire input:++>>> runWriterT $ runProxy $ fromListS [3, 4, 9] >-> raiseK printD >-> headD+3+4+9+((), First {getFirst = Just 3})++    Use the versions that don't prematurely terminate if you are running+    multiple folds or if you want to continue to use the rest of the input when+    the fold is done.  Use the versions that do prematurely terminate if+    collecting that single fold is the entire purpose of the session.+-}++{- $resource+    This core library provides utilities for lazily streaming from resources,+    but does not provide utilities for lazily managing resource allocation and+    deallocation.  To frame the problem, let's assume that we try to be clever+    and write a streaming utility that lazily opens a file only in response to+    a 'request', such as the following 'Producer':++> readFile' :: FilePath -> () -> Producer p String IO+> readFile' file () = runIdentityP $ do+>     h <- lift $ openFile file ReadMode+>     lift $ putStrLn "Opening file"+>     hGetLineS h ()+>     lift $ putStrLn "Closing file"+>     lift $ hClose h++    This works well if we fully demand the file:++>>> runProxy $ readFile' "test.txt" >-> printD+Opening file+"Line 1"+"Line 2"+"Line 3"+Closing file++    This also works well if we never demand the file at all, in which case we+    never open it:++>>> runProxy $ readFile' "test.txt" >-> return+-- Outputs nothing++    But it gives exactly the wrong behavior if we partially demand the file:++>>> runProxy $ readFile' "test.txt" >-> takeB_ 1 >-> printD+Opening file+"Line 1"++    Notice that this does not close the file, because once @takeB_ 1@ terminates+    it terminates the entire 'Session' and @readFile'@ does not get a chance to+    finalize the file.++    I will release a separate library in the near future that offers lazy+    resource management, too, but in the meantime I advise that you use one of+    the following two strategies to guarantee deterministic resource+    deallocation.++    The first approach opens all resources before running the session and close+    them all afterward.  For example, if I wanted to emulate the Unix @cp@+    command, streaming one line at a time, I would write:++> import System.IO+>+> cp :: FilePath -> FilePath -> IO ()+> cp inFile outFile =+>     withFile file1 ReadMode  $ \hIn  ->+>     withFile file2 WriteMode $ \hOut ->+>     runProxy $ hGetLineS hIn >-> hPutLineS hOut2++    The advantage of this approach is that it:++    * is straightforward,++    * requires no special integration with existing libraries, and++    * is exception safe.++    The disadvantage is that this does not lazily allocate resources, nor does+    this promptly deallocate them.++    The second approach is to use something like 'ResourceT' (from the+    @resourceT@ package) to register finalizers and ensure they get released+    deterministically.  You may prefer this approach if you have previously used+    the @conduit@ library, which uses 'ResourceT' in its base monad to offer+    resource determinism.  You can use 'ResourceT' with @pipes@, too, just by+    including it in the base monad.++    I plan to release a lazy resource management library very soon built on top+    of @pipes@ that behaves similarly to 'ResourceT'.  The main advantages of+    this upcoming implementation will be that it:++    * uses a simpler and pure implementation++    * obeys several useful theoretical laws++    * requires no dependencies other than @pipes@++    However, if you don't need this extra power, then just stick to the former+    simpler approach.  I plan to release all standard libraries to be agnostic+    of the finalization approach to let you use which one you prefer.+-}++{- $extend+    This library provides several extensions that add features on top of the+    base 'Proxy' API.  These extensions behave like monad transformers, except+    that they also lift the 'Proxy' class through the extension so that the+    extended proxy can still 'request', 'respond', compose with other proxies:++> instance (Proxy p) => Proxy (IdentityP p)  -- Equivalent to IdentityT+> instance (Proxy p) => Proxy (EitherP e p)  -- Equivalent to EitherT+> instance (Proxy p) => Proxy (MaybeP    p)  -- Equivalent to MaybeT+> instance (Proxy p) => Proxy (StateP  s p)  -- Equivalent to StateT+> instance (Proxy p) => Proxy (WriterP w p)  -- Equivalent to WriterT++    Each of these proxy transformers provides the same API as the equivalent+    monad transformer (sometimes even more).  The following sections show some+    common problems that these proxy transformers solve.+-}++{- $error++    Our previous @promptInt@ example suffered from one major flaw:++> promptInt2 :: (Proxy p) => () -> Producer p Int (EitherT String IO) r+> promptInt2 () = runIdentityP $ forever $ do+>     str <- lift $ lift $ do+>         putStrLn "Enter an Integer:"+>         getLine+>     case readMay str of+>         Nothing -> lift $ left "Could not read Integer"+>         Just n  -> respond n++    There is no way to recover from the error and resume streaming data.  You+    can only handle 'Left' value after using 'runProxy', but by then it is too +    late.++    We can solve this by switching the order of the two monad transformers, but+    using 'EitherP' this time instead of 'EitherT':++> import qualified Control.Proxy.Trans.Either as E+>+> --               Proxy transformers play+> --               nice with type synonyms --++> --                                         |+> --                                         v+> promptInt3 :: (Proxy p) => () -> Producer (E.EitherP String p) Int IO r+> -- i.e.       (Proxy p) => () -> EitherP String p C () () Int IO r+>+> promptInt3 () = forever $ do+>     str <- lift $ do+>         putStrLn "Enter an Integer:"+>         getLine+>     case readMay str of+>         Nothing -> E.throw "Could not read Integer"+>         Just n' -> respond n++    This example does not need 'runIdentityP' (nor would that type-check)+    because the 'EitherP' proxy transformer gives the compiler enough+    information to generalize the constraints.++    We've swapped the order of the transformers, so now we use 'runEitherK'+    first to unwrap the 'EitherP' followed by 'runProxy'.++> runEitherK+>  :: (q -> EitherP p a' a b' b m r) -> (q -> p a' a b' b m (Either e r))++>>> runProxy $ runEitherK $ promptInt3 >-> printer :: IO (Either String r)+Enter an Integer:+Hello<Enter>+Left "Could not read Integer"++    Notice how we can directly compose @printer@ with @promptInt@.+    This works because @printer@'s base proxy type is completely polymorphic+    over the 'Proxy' type class and doesn't use any features specific to any+    proxy transformers:++>                  'p' type-checks as anything --++>                   that implements 'Proxy'      |+>                                                v+> printer :: (Proxy p, Show a) => () -> Consumer p a IO r++    This means that you can compose @printer@ with anything that implements the+    'Proxy' type class, including 'EitherP', without any lifting.++    'EitherP' lets us catch and handle errors locally without disturbing other+    proxies.  For example, I can define a heartbeat function that just restarts+    a given proxy each time it raises an error:++> heartbeat+>  :: (Proxy p)+>  => E.EitherP String p a' a b' b IO r+>  -> E.EitherP String p a' a b' b IO r+> heartbeat p = p `E.catch` \err -> do+>     lift $ putStrLn err  -- Print the error+>     heartbeat p          -- Restart 'p'++    This uses the 'catch' function from "Control.Proxy.Trans.Either", which+    lets you catch and handle errors locally without disturbing other proxies.++>>> runProxy $ E.runEitherK $ (heartbeat . promptInt3) >-> takeB_ 2 >-> printer+Enter an Integer:+Hello<Enter>+Could not read Integer+Enter an Integer+8+Received a value:+8+Enter an Integer+0+Received a value:+0++    It's very easy to prove that 'EitherP' has only a local effect.  In fact,+    we can run it entirely locally like so:++>>> runProxy $ (E.runEitherK $ heartbeat . promptInt3) >-> takeB_ 2 >-> printer++    Proxy transformers do not use the base monad at all, so you can use them to+    isolate effects from other proxies, as the next section demonstrates.+-}++{- $state+    The 'StateP' proxy lets you embed local state into any 'Proxy' computation.+    For example, we might want to gratuitously use state to generate successive+    numbers:++> import qualified Control.Proxy.Trans.State as S+>+> increment :: (Monad m, Proxy p) => () -> Producer (S.StateP Int p) Int m r+> increment () = forever $ do+>     n <- S.get+>     respond n+>     S.put (n + 1)++    We could then embed it locally into any 'Proxy', such as the following one:++> numbers :: (Monad m, Proxy p) => () -> Producer p Int m ()+> numbers () = runIdentityP $ do+>     (takeB_ 5 <-< S.evalStateK 10 increment) ()+>     S.evalStateK 1  (takeB_ 3 <-< increment) () -- This works, too!++>>> runProxy $ numbers >-> printD+10+11+12+13+14+1+2+3++    We can also prove the effect is local even when you directly compose two+    'StateP' proxies before running them.  Let's define a stateful consumer:++> increment2 :: (Proxy p) => () -> Consumer (S.StateP Int p) Int IO r+> increment2 () = forever $ do+>     nOurs   <- S.get+>     nTheirs <- request ()+>     lift $ print (nTheirs, nOurs)+>     S.put (nOurs + 2)++    .. and hook it up directly to @increment@:++>>> runProxy $ S.evalStateK 0 $ increment >-> takeB_ 3 >-> increment2+(0, 0)+(1, 2)+(2, 4)++    They each share the same initial state, but they isolate their own side+    effects completely from each other.+-}++{- $branch+    So far we've only considered linear chains of proxies, but @pipes@ allows+    you to branch these chains and generate more sophisticated topologies.  The+    trick is to simply nest the 'Proxy' monad transformer within itself.++    For example, if I want to zip two inputs, I can just define the following+    triply nested proxy:++> zipD+>  :: (Monad m, Proxy p1, Proxy p2, Proxy p3)+>  => () -> Consumer p1 a (Consumer p2 b (Consumer p3 (a, b) m)) r+> zipD = runIdentityP . hoist (runIdentityP . hoist runIdentityP) $ forever $ do+>     -- Yes, this 'runIdentityP' mess is necessary.  Sorry!+>+>     a <- request ()               -- Request from the outer 'Consumer'+>     b <- lift $ request ()        -- Request from the inner 'Consumer'+>     lift $ lift $ respond (a, b)  -- Respond to the 'Producer'++    'zipD' behaves analogously to a curried function.  We partially apply it to+    each layer using composition and 'runProxyK' or 'runProxy':++> -- 1st application+> p1 = runProxyK $ zipD <-< fromListS [1..3]+>+> -- 2nd application+> p2 = runProxyK $ p1 <-< fromListS [4..]+>+> -- 3rd application+> p3 = runProxy $ printD <-< p2++>>> p3+(1, 4)+(2, 5)+(3, 6)++    You can use this trick to fork output, too:++> fork+>  :: (Monad m, Proxy p1, Proxy p2, Proxy p3)+>  => () -> Consumer p1 a (Producer p2 a (Producer p3 a m)) r+> fork () =+>     runIdentityP . hoist (runIdentityP . hoist runIdentityP) $ forever $ do+>         a <- request ()          -- Request output from the 'Consumer'+>         lift $ respond a         -- Send output to the outer 'Producer'+>         lift $ lift $ respond a  -- Send output to the inner 'Producer'++    Again, we just keep partially applying it until it is fully applied:++> -- 1st application+> p1 = runProxyK $ fork <-< fromListS [1..3]+>+> -- 2nd application+> p2 = runProxyK $ raiseK printD <-< mapD (> 2) <-< p1+>+> -- 3rd application+> p3 = runProxy  $ printD <-< mapD show <-< p2++>>> p3+False+"1"+False+"2"+True+"3"++    You can even merge or fork proxies that use entirely different feature sets:++> p1 = runProxyK $ S.evalStateK 0 $ fork <-< increment+>+> p2 = runProxyK $ raiseK printD <-< mapD (+ 10) <-< p1+>+> p3 = runProxy  $ E.runEitherK $ printD <-< (takeB_ 3 >=> E.throw) <-< p2++>>> p3+10+0+11+1+12+2+Left ()++    We just forked a @(StateP p1)@ proxy and read out the result in both a+    generic @p2@ proxy and an @(EitherP p3)@ proxy.  That's pretty crazy, but it+    gives you a sense of how versatile and robust proxies can be.++    You can implement arbitrary branching topologies using this trick.  However,+    I want to mention a few caveats:++    * The intermediate partially applied type signatures will be ugly as sin.+      I warned you.++    * You cannot implement cyclic topologies (and cyclic topologies do not make+      sense for proxies anyway)++    * You cannot use this trick to implement a polymorphic zip function of the+      following form:++> zip'  -- You can't define this+>  :: (Monad m, Proxy p)+>  => (() -> Producer p a      m r)+>  -> (() -> Producer p b      m r)+>  -> (() -> Producer p (a, b) m r)++    Partial application requires selecting a 'Proxy' instance, which is why you+    cannot define @zip'@.  You /can/ define a @zip'@ specialized to a concrete+    'Proxy' instance, but I don't really recommend doing that since you should+    always strive to write polymorphic proxies to avoid locking your user into+    a particular feature set.++    With those caveats out of the way, this approach affords many indispensable+    features that other approaches do not allow:++    * It does not require extending the 'Proxy' type class++    * It handles almost every branching scenario, including more complicated+      situations like concurrent interleavings++    * You can branch and merge mixtures of 'Server's, 'Client's, and 'Proxy's++    * You can branch and merge heterogeneous feature sets++    * It is completely polymorphic over the 'Proxy' class and uses no+      implementation-specific details+-}++{- $proxytrans+    There is one last scenario that you will eventually encounter: mixing+    proxies that have incompatible proxy transformer stacks.  You solve this the+    exact same way you mix different monad transformer stacks, except that+    instead of using 'lift' and 'hoist' you use 'liftP' and 'hoistP'.++    For example, we might want to mix @promptInt3@ and @increment2@:++> promptInt3 :: (Proxy p) => () -> Producer (E.EitherP String p) Int IO r+>+> increment2 :: (Proxy p) => () -> Consumer (S.StateP Int p) Int IO r++    Unfortunately, they use two different feature sets so neither one is fully+    polymorphic over the 'Proxy' class and we cannot directly compose them.++    Fortunately, all proxy transformers implement the 'ProxyTrans' class,+    analogous to the 'MonadTrans' class for transformers:++> class ProxyTrans t where+>     liftP+>       :: (Monad m, Proxy p)+>       => p a' a b' b m r -> t p a' a b' b m r+>+>  -- mapP is slightly more elegant+>     mapP+>      :: (Monad m, Proxy p)+>      => (q -> p a' a b' b m r) -> (q -> t p a' a b' b m r)+>     mapP = (liftP . )++    It's very easy to use.  Just use 'mapP' (equivalent to @(liftP .)@ to lift+    one proxy transformer to match another one.  For example, we can 'mapP'+    @increment2@ to match @promptInt3@:++> promptInt3 >-> mapP increment2+>  :: (Proxy p) => () -> Session (EitherP String (StateP Int p)) IO r++>>> runProxy $ S.evalStateK 0 $ E.runEitherK $ promptInt3 >-> mapP increment2+Enter an Integer:+4<Enter>+(4, 0)+Enter an Integer:+5<Enter>+(5, 2)+Enter an Integer:+Hello<Enter>+Left "Could not read Integer"++    ... or we could instead 'mapP' @promptInt3@ to match @increment2@ and switch+    the order of the two proxy transformers:++> mapP promptInt3 >-> increment2+>  :: (Proxy p) => () -> Session (StateP Int (EitherP String p)) IO r++>>> runProxy $ E.runEitherK $ S.evalStateK 0 $ mapP promptInt3 >-> increment2+Enter an Integer:+4<Enter>+(4, 0)+Enter an Integer:+5<Enter>+(5, 2)+Enter an Integer:+Hello<Enter>+Left "Could not read Integer"++    Like monad transformers, proxy transformers lift a base 'Monad' instance+    to an extended 'Monad' instance.  'liftP' exactly mirrors the 'lift'+    function from 'MonadTrans'.  'liftP' takes some base proxy, @p@, that+    implements 'Monad' and \"lift\"s it to an extended proxy, @(t p)@, that also+    implements 'Monad'.++    So for example, I could do something like:++> do liftP $ actionInBaseProxy+>    actionInExtendedProxy++    Monad transformers impose certain laws to ensure that this lifting is+    correct.  These are known as the monad transformer laws;++> (lift .) (f >=> g) = (lift .) f >=> (lift .) g+>+> (lift .) return = return++    If you convert these laws to @do@ notation, they just say:++> do  x <- lift m  =  lift $ do x <- m+>     lift (f x)                f x+>+> lift (return r) = return r++    Proxy transformers require the exact same laws to ensure that they lift the+    base monad to the extended monad correctly.  Just replace 'lift' with+    'liftP':++> (liftP .) (f >=> g) = (liftP .) f >=> (liftP .) g+>+> (liftP .) return = return++    The only difference is that I also include 'mapP' in the 'ProxyTrans' type+    class for convenience, which sweetens these laws a little bit:++> mapP = (lift .)+>+> mapP (f >=> g) = mapP f >=> mapP g  -- These are functor laws!+>+> mapP return = return++    However, proxy transformers do one extra thing above and beyond ordinary+    monad transformers.  Proxy transformers lift the 'Proxy' type class, meaning+    that if the base type implements 'Proxy', so does the extended type.++    This means that we need a set of laws that guarantee that the proxy+    transformer lifts the 'Proxy' instance correctly.  I call these laws the+    \"proxy transformer laws\":++> mapP (f >-> g) = mapP f >-> mapP g  -- These are functor laws, too!+>+> mapP idT = idT++    In other words, a proxy transformer defines a functor from the base+    composition to the extended composition!  Neat!++    But we're not even done, because proxies actually form three other+    categories, only one of which I have mentioned so far, and proxy+    transformers lift these three other categories, too:++> -- The push-based category+>+> mapP (f >~> g) = mapP f >~> mapP g+>+> mapP coidT = coidT++> -- The "request" category+>+> mapP (f \>\ g) = mapP f \>\ mapP g+>+> mapP request = request++> -- The "respond" category+>+> mapP (f />/ g) = mapP f />/ mapP g+>+> mapP respond = respond++    I never even mentioned those last two categories because they are more+    exotic and you probably never need to use them.  However, even if we never+    use those categories they still guarantee two really important laws that we+    should remember:++> mapP request = request+>+> mapP respond = respond++    We can translate those to 'liftP' to get:++> liftP $ request a' = request a'+>+> liftP $ respond b  = respond b++    In other words, 'request' and 'respond' in the extended proxy must behave+    exactly the same as lifting 'request' and 'respond' from the base proxy.++    All the proxy transformers in this library obey the proxy transformer laws,+    which ensure that 'liftP' / 'mapP' always do \"the right thing\".++    Proxy transformers also implement 'hoistP' from the 'PFunctor' class in+    "Control.PFunctor".  This exactly parallels 'hoist' for monad transformers.++    Just like monad transformers, we can mix two completely exotic proxy+    transformer stacks using a combination of 'liftP' and 'hoistP'.  Here's the+    proxy transformer equivalent of the previous example I gave:++> p1 :: (Proxy p) => a' -> StateP s (ReaderP i p) a' a a' a m r+> p2 :: (Proxy p) => a' -> MaybeP   (WriterP w p) a' a a' a m r++    As before, I can interleave their proxy transformers through judicious use+    of 'hoistP' and 'liftP'++> pSequence+>  :: (Proxy p) => StateP s (MaybeP (ReaderP i (WriterP w p))) a' a a' a r+> pSequence a' = do+>     hoistP (liftP . hoistP liftP) (p1 a')+>     liftP (hoistP liftP (p2 a'))++    ... but unlike ordinary monad transformers I could instead mix them by+    composition, too!++> pCompose+>  :: (Proxy p) => StateP s (MaybeP (ReaderP i (WriterP w p))) a' a a' a r+> pCompose =+>      hoistP (liftP . hoistP liftP) . p1+>  >-> liftP . hoistP liftP . p2+-}++{- $conclusion+    The @pipes@ library emphasizes the reuse of a small set of core abstractions+    grounded in theory to implement all functionality:++    * Monads++    * Proxies: ('>->'), 'request', and 'respond'++    * Monad Transformers and Functors on Monads: 'lift' and 'hoist'++    * Proxy Transformers and Functors on Proxies: 'liftP' and 'hoistP'++    However, I don't expect everybody to immediately understand how so few+    primitives can implement such a wide variety of features.  This tutorial+    gives a taste of how many interesting ways you can combine these few+    abstractions, but these examples barely scratch the surface, despite this+    tutorial's length.  So if you don't know how to implement something using+    @pipes@, just ask me and I will be happy to help. -}
− Data/Closed.hs
@@ -1,9 +0,0 @@-{-| An empty type that gives cleaner type signatures. -}--module Data.Closed (-    -- * Closed-    C-    ) where---- | The empty type, denoting a \'@C@\'losed end-data C = C -- Not exported, but I write it to keep the library Haskell98
pipes.cabal view
@@ -1,5 +1,5 @@ Name: pipes-Version: 2.5.0+Version: 3.0.0 Cabal-Version: >=1.14.0 Build-Type: Simple License: BSD3@@ -7,40 +7,33 @@ Copyright: 2012 Gabriel Gonzalez Author: Gabriel Gonzalez Maintainer: Gabriel439@gmail.com-Stability: Experimental Bug-Reports: https://github.com/Gabriel439/Haskell-Pipes-Library/issues Synopsis: Compositional pipelines Description:-  \"Iteratees done right\".  This library implements-  iteratees\/enumerators\/enumeratees simply and elegantly, using different-  naming conventions.+  \"Coroutines done right\".  This library generalizes+  iteratees\/enumerators\/enumeratees simply and elegantly.   .-  Advantages over traditional iteratee implementations:+  Advantages over traditional iteratee\/coroutine implementations:   .-  * /Concise API/: This library uses a few simple abstractions with a very high-    power-to-weight ratio to reduce adoption time.+  * /Concise API/: Use three simple commands: ('>->'), 'request', and 'respond'   .-  * /Bidirectionality/: The library offers bidirectional communication+  * /Bidirectionality/: Implement duplex channels   .-  * /Blazing fast/: Currently the fastest iteratee implementation+  * /Blazing fast/: Implementation tuned for speed   .-  * /Clear semantics/: All abstractions are grounded in category theory, which-    leads to intuitive behavior (and fewer bugs, if any!).+  * /Elegant semantics/: Use practical category theory   .-  * /Extension Framework/: You can elegantly mix and match extensions to the-    base type and easily create your own!+  * /Extension Framework/: Mix and match extensions and create your own   .+  * /Lightweight Dependency/: @pipes@ depends only on @transformers@ and+    compiles rapidly+  .   * /Extensive Documentation/: Second to none!   .-  I recommend you begin by reading "Control.Pipe.Tutorial" which introduces the-  basic concepts using the simpler unidirectional 'Pipe' API.  Then move on to-  "Control.Proxy.Tutorial", which introduces the 'Proxy' type which forms the-  core abstraction of this library.  To use extensions or define your own, check-  out "Control.Proxy.Trans.Tutorial".+  Import "Control.Proxy" to use the library.   .-  I will soon replace "Control.Frame" with a superior resource-management-  solution, so new users of the library should avoid using it.-Category: Control, Pipe, Proxies+  Read "Control.Proxy.Tutorial" for a really extensive tutorial.+Category: Control, Pipes, Proxies Tested-With: GHC ==7.4.1 Source-Repository head     Type: git@@ -49,32 +42,28 @@ Library     Build-Depends:         base >= 4 && < 5,-        index-core,         transformers >= 0.2.0.0     Exposed-Modules:-        Control.Frame,-        Control.Frame.Tutorial,-        Control.IMonad.Trans.Free,         Control.MFunctor,+        Control.PFunctor,+        Control.Pipe,         Control.Proxy,-        Control.Proxy.Core,         Control.Proxy.Class,+        Control.Proxy.Core,+        Control.Proxy.Core.Fast,+        Control.Proxy.Core.Correct,         Control.Proxy.Pipe,+        Control.Proxy.Synonym,         Control.Proxy.Trans,         Control.Proxy.Trans.Either,         Control.Proxy.Trans.Identity,         Control.Proxy.Trans.Maybe,         Control.Proxy.Trans.Reader,         Control.Proxy.Trans.State,-        Control.Proxy.Trans.Tutorial,         Control.Proxy.Trans.Writer,         Control.Proxy.Tutorial,         Control.Proxy.Prelude,         Control.Proxy.Prelude.Base,         Control.Proxy.Prelude.IO,-        Control.Proxy.Prelude.Kleisli,-        Control.Pipe,-        Control.Pipe.Core,-        Control.Pipe.Tutorial,-        Data.Closed+        Control.Proxy.Prelude.Kleisli     Default-Language: Haskell98