{-# LANGUAGE FlexibleContexts #-}-- | Higher-level functions to interact with the elements of a stream. Most of-- these are based on list functions.---- Note that these functions all deal with individual elements of a stream as a-- sort of \"black box\", where there is no introspection of the contained-- elements. Values such as @ByteString@ and @Text@ will likely need to be-- treated specially to deal with their contents properly (@Word8@ and @Char@,-- respectively). See the "Data.Conduit.Binary" and "Data.Conduit.Text"-- modules.moduleData.Conduit.List(-- * SourcessourceList,sourceNull-- * Sinks-- ** Pure,fold,take,drop,head,zip,zipSinks,peek,consume,sinkNull-- ** Monadic,foldM,mapM_-- Conduits-- ** Pure,map,concatMap,concatMapAccum,groupBy,isolate,filter-- ** Monadic,mapM,concatMapM,concatMapAccumM)whereimportPrelude(($),return,(==),(-),Int,(.),id,Maybe(..),Monad,Bool(..),Ordering(..),(>>),flip,seq,otherwise)importData.ConduitimportData.Conduit.Internal(pipeClose,runFinalize)importData.Monoid(mempty)importData.Void(absurd)importControl.Monad(liftM,liftM2)-- | A strict left fold.---- Since 0.3.0fold::Monadm=>(b->a->b)->b->Sinkambfoldfaccum0=goaccum0wheregoaccum=NeedInput(pushaccum)(returnaccum)pushaccuminput=letaccum'=faccuminputinaccum'`seq`goaccum'-- | A monadic strict left fold.---- Since 0.3.0foldM::Monadm=>(b->a->mb)->b->SinkambfoldMfaccum0=sinkStateaccum0(\accuminput->doaccum'<-faccuminputreturn$StateProcessingaccum')return-- | Apply the action to all values in the stream.---- Since 0.3.0mapM_::Monadm=>(a->m())->Sinkam()mapM_f=NeedInputpushclosewherepushinput=PipeM(finput>>return(NeedInputpushclose))(return())close=return()-- | Convert a list into a source.---- Since 0.3.0sourceList::Monadm=>[a]->SourcemasourceList[]=DoneNothing()sourceList(x:xs)=HaveOutput(sourceListxs)(return())x-- | Ignore a certain number of values in the stream. This function is-- semantically equivalent to:---- > drop i = take i >> return ()---- However, @drop@ is more efficient as it does not need to hold values in-- memory.---- Since 0.3.0drop::Monadm=>Int->Sinkam()drop0=NeedInput(flipDone().Just)(return())dropcount=NeedInputpush(return())wherecount'=count-1push_|count'==0=DoneNothing()|otherwise=dropcount'-- | Take some values from the stream and return as a list. If you want to-- instead create a conduit that pipes data to another sink, see 'isolate'.-- This function is semantically equivalent to:---- > take i = isolate i =$ consume---- Since 0.3.0take::Monadm=>Int->Sinkam[a]takecount0=gocount0idwheregocountfront=NeedInput(pushcountfront)(return$front[])push0frontx=Done(Justx)(front[])pushcountfrontx|count'==0=DoneNothing(front[x])|otherwise=NeedInput(pushcount'front')(return$front'[])wherecount'=count-1front'=front.(x:)-- | Take a single value from the stream, if available.---- Since 0.3.0head::Monadm=>Sinkam(Maybea)head=NeedInputpushclosewherepushx=DoneNothing(Justx)close=returnNothing-- | Look at the next value in the stream, if available. This function will not-- change the state of the stream.---- Since 0.3.0peek::Monadm=>Sinkam(Maybea)peek=NeedInputpushclosewherepushx=Done(Justx)(Justx)close=returnNothing-- | Apply a transformation to all values in a stream.---- Since 0.3.0map::Monadm=>(a->b)->Conduitambmapf=NeedInputpushclosewherepushi=HaveOutput(NeedInputpushclose)(return())(fi)close=mempty-- | Apply a monadic transformation to all values in a stream.---- If you do not need the transformed values, and instead just want the monadic-- side-effects of running the action, see 'mapM_'.---- Since 0.3.0mapM::Monadm=>(a->mb)->ConduitambmapMf=NeedInputpushclosewherepush=flipPipeM(return()).liftM(HaveOutput(NeedInputpushclose)(return())).fclose=mempty-- | Apply a transformation to all values in a stream, concatenating the output-- values.---- Since 0.3.0concatMap::Monadm=>(a->[b])->ConduitambconcatMapf=NeedInputpushclosewherepush=haveMore(NeedInputpushclose)(return()).fclose=mempty-- | Apply a monadic transformation to all values in a stream, concatenating-- the output values.---- Since 0.3.0concatMapM::Monadm=>(a->m[b])->ConduitambconcatMapMf=NeedInputpushclosewherepush=flipPipeM(return()).liftM(haveMore(NeedInputpushclose)(return())).fclose=mempty-- | 'concatMap' with an accumulator.---- Since 0.3.0concatMapAccum::Monadm=>(a->accum->(accum,[b]))->accum->ConduitambconcatMapAccumfaccum=conduitStateaccumpushclosewherepushstateinput=let(state',result)=finputstateinreturn$StateProducingstate'resultclose_=return[]-- | 'concatMapM' with an accumulator.---- Since 0.3.0concatMapAccumM::Monadm=>(a->accum->m(accum,[b]))->accum->ConduitambconcatMapAccumMfaccum=conduitStateaccumpushclosewherepushstateinput=do(state',result)<-finputstatereturn$StateProducingstate'resultclose_=return[]-- | Consume all values from the stream and return as a list. Note that this-- will pull all values into memory. For a lazy variant, see-- "Data.Conduit.Lazy".---- Since 0.3.0consume::Monadm=>Sinkam[a]consume=goidwheregofront=NeedInput(pushfront)(return$front[])pushfrontx=go(front.(x:))-- | Grouping input according to an equality function.---- Since 0.3.0groupBy::Monadm=>(a->a->Bool)->Conduitam[a]groupByf=conduitState[]pushclosewherepush[]v=return$StateProducing[v][]pushs@(x:_)v=iffxvthenreturn$StateProducing(v:s)[]elsereturn$StateProducing[v][s]closes=return[s]-- | Ensure that the inner sink consumes no more than the given number of-- values. Note this this does /not/ ensure that the sink consumes all of those-- values. To get the latter behavior, combine with 'sinkNull', e.g.:---- > src $$ do-- > x <- isolate count =$ do-- > x <- someSink-- > sinkNull-- > return x-- > someOtherSink-- > ...---- Since 0.3.0isolate::Monadm=>Int->Conduitamaisolatecount0=conduitStatecount0pushclosewhereclose_=return[]pushcountx=doifcount==0thenreturn$StateFinished(Justx)[]elsedoletcount'=count-1return$ifcount'==0thenStateFinishedNothing[x]elseStateProducingcount'[x]-- | Keep only values in the stream passing a given predicate.---- Since 0.3.0filter::Monadm=>(a->Bool)->Conduitamafilterf=NeedInputpushclosewherepushi|fi=HaveOutput(NeedInputpushclose)(return())ipush_=NeedInputpushcloseclose=mempty-- | Ignore the remainder of values in the source. Particularly useful when-- combined with 'isolate'.---- Since 0.3.0sinkNull::Monadm=>Sinkam()sinkNull=NeedInputpushclosewherepush_=sinkNullclose=return()-- | A source that returns nothing. Note that this is just a type-restricted-- synonym for 'mempty'.---- Since 0.3.0sourceNull::Monadm=>SourcemasourceNull=mempty-- | Combines two sources. The new source will stop producing once either-- source has been exhausted.---- Since 0.3.0zip::Monadm=>Sourcema->Sourcemb->Sourcem(a,b)zip(Done_())(Done_())=DoneNothing()zip(Done_())(HaveOutput_close_)=PipeM(runFinalizeclose>>return(DoneNothing()))closezip(HaveOutput_close_)(Done_())=PipeM(runFinalizeclose>>return(DoneNothing()))closezip(Done_())(PipeM_close)=PipeM(runFinalizeclose>>return(DoneNothing()))closezip(PipeM_close)(Done_())=PipeM(runFinalizeclose>>return(DoneNothing()))closezip(PipeMmxclosex)(PipeMmyclosey)=PipeM(liftM2zipmxmy)(closex>>closey)zip(PipeMmxclosex)y@(HaveOutput_closey_)=PipeM(liftM(\x->zipxy)mx)(closex>>closey)zipx@(HaveOutput_closex_)(PipeMmyclosey)=PipeM(liftM(\y->zipxy)my)(closex>>closey)zip(HaveOutputsrcxclosexx)(HaveOutputsrcycloseyy)=HaveOutput(zipsrcxsrcy)(closex>>closey)(x,y)zip(NeedInput_c)right=zipcrightzipleft(NeedInput_c)=zipleftc-- | Combines two sinks. The new sink will complete when both input sinks have-- completed.---- If both sinks finish on the same chunk, and both report leftover input,-- arbitrarily yield the left sink's leftover input.---- Since 0.4.1zipSinks::Monadm=>Sinkimr->Sinkimr'->Sinkim(r,r')zipSinks=zipSinks'EQzipSinks'::Monadm=>Ordering->Sinkimr->Sinkimr'->Sinkim(r,r')zipSinks'byInputUsed=(><)wherePipeMmpxmx><py=PipeM(liftM(><py)mpx)(liftM2(,)mx(pipeClosepy))px><PipeMmpymy=PipeM(liftM(px><)mpy)(liftM2(,)(pipeClosepx)my)Doneixx><Doneiyy=Donei(x,y)wherei=casebyInputUsedofEQ->iy>>ixGT->ixLT->iyNeedInputfpxpx><NeedInputfpypy=NeedInput(\i->zipSinks'EQ(fpxi)(fpyi))(px><py)NeedInputfpxpx><py=NeedInput(\i->zipSinks'GT(fpxi)py)(px><py)px><NeedInputfpypy=NeedInput(\i->zipSinks'LTpx(fpyi))(px><py)HaveOutput__o><_=absurdo_><HaveOutput__o=absurdo