úÎeyaý6      !"#$%&'()*+,-./012345Safe=A free monad transformer alternates nesting the base functor f and the base monad m.f, - The functor that generates the free monadm - The base monadr - The type of the return valueRThis type commonly arises in coroutine/iteratee libraries under various names.The  type is isomorphic to: ,data Free f r = Pure r | Wrap (f (Free f r))`... except that if you want to pattern match against those constructors, you must first use  to unwrap the value first.KSimilarly, you don't use the raw constructors to build a value of type *. You instead use the smart constructors 6 (from Control.Applicative) and .     SafeOT 1A 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 valueWait 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 (7)/(8) from Control.CategoryCorresponds to (9) 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 Safe#A # is a $4 that doesn't need input and doesn't generate output$A pipe type that combines ( and ': to enable both prompt and deterministic finalization.\The name connotes a stack frame, since finalized pipes can be thought of as forming the ;¬ of stack frames, where upstream finalization is equivalent to finalizing the heap, and downstream finalization is equivalent to throwing an exception up the stack.The type is equivalent to: *type Frame a b m r = Prompt Ensure a b m r'A pipe type that 's deterministic finalizationˆThe finalization machinery uses the input and output ends in different ways to finalize the pipe when another pipe terminates first.JIf an upstream pipe terminates first, the current pipe will receive a <œ once. This allows it to finalize itself and if it terminates then its return value takes precedence over upstream's return value. However, if it os again, it defers to upstream's return value and never regains control. You do not need to "rethrow" the <; (nor can you): composition takes care of this for you.cOn the output end, the pipe must supply its most up-to-date finalizer alongside every value it ìs downstream. This finalizer is guaranteed to be called if downstream terminates first. You do not need to relay upstream finalizers alongside the pipe's own finalizer (nor can you): composition takes care of this for you.zThe combination of these two tricks allows a bidirectional guarantee of deterministic finalization that satisfies the ; laws.(3An illustrative type synonym that demonstrates how ( finalization worksðThis type simulates a parametrized monad by breaking it up into two monads where the first monad returns the second one. The first monad permits any pipe code and the second monad only permits pipe code that doesn't need input.For example if p = Pipe&, the first monad becomes an ordinary $ and the second monad becomes a : 0Prompt Pipe a b m r = Pipe a b m (Pipe () b m r)ÁThe pipe does not require input by the time it reaches the second block, meaning that the finalization machinery can safely finalize upstream resources the moment. The earlier you use +E the input end, the more promptly you release upstream resources.½The finalization machinery also finalizes downstream pipes when the second monad terminates. I use this trick to ensure a strict ordering of finalizers from upstream to downstream.I don't actually use the (Š type synonym, since that would require newtyping everything, but I will reference it in documentation to clarify type signatures.)Like 8, but also yields an empty finalizer alongside the value*Like , but ignores all <s and just awaits again+Use this to mark when a $7 no longer requires input. The earlier the better!,Use this to bind to the +d half of the $Q if you want to continue where it left off but you still don't require input.(This function would not be necessary if (Y were implemented as a parametrized monad, so if it seems ugly, that's because it is.- Use this to - a $@ if you change your mind and decide you want to continue to  input after all.2This postpones finalization of upstream until you + the input end again.. catchP m p registers mB to be called only if another composed pipe terminates before p is done.// is like ., except that it also calls the finalizer if p completes normally.0Corresponds to : from Control.Category1Corresponds to (7)/(8) from Control.Category2Corresponds to (9) from Control.Category3 Convert a $ back to the base monad. !"#$%&'()*+,-./=>?@ABC012345 !"#$%&'()*+,-./0123('$%&#)*+,-./120 !"3 !"#$%&'()*+,-./=>?@ABC012345Safe%  !"#$%&'()*+,-./0123D      !"##$%&&'()*+,-./01234567897:;7:<7:=7:>7:?78@ABCDEFGH"pipes-2.0.0-L6dFNiP3uZc1f8piM28CruControl.Monad.Trans.FreeControl.Pipe.CommonControl.Pipe.Final Control.PipeFreeTrunFreeTFreeFreeFPureWrapwraprunFree$fMonadTransFreeT$fApplicativeFreeT$fFunctorFreeT $fMonadFreeTLazyunLazyPipelineConsumerProducerPipePipeFAwaitYieldawaityieldpipe<+<>+>idPrunPipe$fCategoryTYPELazy$fFunctorPipeFFrameCunFrameCStackFrameunFrameEnsurePromptyieldFawaitFclose bindClosedreopencatchPfinallyPidF<-<>->runFrame$fCategoryTYPEFrameC$fFunctorFramebaseGHC.BasepureControl.Category<<<.>>>idCategoryNothing<~<<~|unitmultcomultwarnschedule