úÎ?(;Ÿ9      !"#$%&'()*+,-./012345678Safe  s form a 9/ instance when you rearrange the type variables1A self-contained pipeline that is ready to be runA pipe that consumes valuesA pipe that produces valuesThe base type for pipesa1 - The type of input received from upstream pipesb3 - The type of output delivered to downstream pipesm - The base monadr - The type of the return valueThe base functor for the  type Wait for input from upstream. / blocks until input is available from upstream. Deliver output downstream. 8 restores control back upstream and binds the result to  . #Convert a pure function into a pipe 2pipe = forever $ do x <- await yield (f x) Corresponds to (:)/(;) from Control.CategoryCorresponds to (<) from Control.CategoryCorresponds to = from Control.CategoryRun the ; monad transformer, converting it back into the base monad. imposes two conditions:9The pipe's input, if any, is trivially satisfiable (i.e. ())The pipe does not   any outputThe latter restriction makes [ less polymorphic than it could be, and I settled on the restriction for three reasons:)It prevents against accidental data loss.aIt prevents wastefully draining a scarce resource by gratuitously demanding values from it.lIt encourages an idiomatic pipe programming style where input is consumed in a structured way using a .ª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       9 9 SafeDQRIndexed equivalent to FreeTIndexed equivalent to FreeFIndexed equivalent to wrapIndexed equivalent to liftF Safe%&QR" s form a 9/ instance when you rearrange the type variables!A self-contained " that is ready to be run"A " is like a  with an indexed input end:b - The type of the "s outputm - The base monadi' - The initial index of the input end ()pen or (losed)j% - The final index of the input end ()pen or (losed)r - The return value#4Base functor for a pipe that can close its input endb - Output typex - Next stepi - Current step's index'?Index representing an open input end, receiving values of type Maybe a(%Index representing a closed input end)?Index representing an open input end, receiving values of type a*$% the most current finalizer for this " alongside the value+%" a value from upstream, returning > if upstream terminates,&9 the input end, calling the finalizers of every upstream "--. a value upstream alongside an empty finalizer..; a value from upstream and terminate if upstream terminates/ catchD m p calls the finalizer m if a downstream " terminates before p finishes.0 catchF m p calls the finalizer m if any " terminates before p finishes.1 finallyD m p calls the finalizer m if a downstream " terminates before p finishes or if p completes normally.2 finallyF m p calls the finalizer m if any " terminates before p finishes or if p completes normally.3Corresponds to (:)/(;) from Control.Category4Corresponds to (<) from Control.Category5Corresponds to = from Control.Category6Run the "9 monad transformer, converting it back to the base monad.6 is the " equivalent to # and requires a self-contained !.! !"#$%&'()*+,-./012?@ABC3456D78 !"#$%&'()*+,-./0123456()'#$%&"!*+,-./012345 6 !"#$%&'()*+,-./012?@ABC3456D7839 49 SafeSafeE      !""#$%& '()*+,-./0123456789:89;89<89=89>8?@ABCDEFG"pipes-2.2.0-2NS2AeUG7PCJecR2BV3lhO Control.PipeControl.IMonad.Trans.Free Control.FrameControl.Frame.TutorialControl.Pipe.TutorialPipeCunPipeCPipelineConsumerProducerPipePipeFAwaitYieldawaityieldpipe<+<>+>idPrunPipe$fCategoryTYPEPipeC$fFunctorPipeFIFreeT runIFreeTIFreeFReturnWrapwrapliftF$fIMonadTransTYPEIFreeT$fIMonadTYPEIFreeT$fIFunctorTYPETYPEIFreeTFrameCunFrameCStackFrameFrameFCloseMCOyieldFawaitFclosecatchDcatchFfinallyDfinallyF<-<>->idFrunFrame$fCategoryTYPEFrameC$fIFunctorTYPETYPEFrameFbaseControl.CategoryCategory<<<.>>>idGHC.BaseNothing<~<<~|heapstackwarn runFrame'