{-# LANGUAGE FlexibleContexts #-}-- | Defines the types for a source, which is a producer of data.moduleData.Conduit.Types.Source(SourceResult(..),Source(..))whereimportControl.Monad.Trans.ResourceimportData.Monoid(Monoid(..))importControl.Monad(liftM)-- | Result of pulling from a source. Either a new piece of data (@Open@), or-- indicates that the source is now @Closed@.---- The @Open@ constructor returns both a new value, as well as a new @Source@,-- which should be used in place of the previous @Source@.---- Since 0.2.0dataSourceResultma=Open(Sourcema)a|ClosedinstanceMonadm=>Functor(SourceResultm)wherefmapf(Openpa)=Open(fmapfp)(fa)fmap_Closed=Closed-- | A @Source@ has two operations on it: pull some data, and close the-- @Source@. Since @Source@ is built on top of 'ResourceT', all acquired-- resources should be automatically released anyway. Closing a @Source@ early-- is merely an optimization to free scarce resources as soon as possible.---- A @Source@ is should free any resources it allocated when either-- @sourceClose@ is called or a @Closed@ is returned. However, based on the-- usage of @ResourceT@, this is simply an optimization.---- Since 0.2.0dataSourcema=Source{sourcePull::ResourceTm(SourceResultma),sourceClose::ResourceTm()}instanceMonadm=>Functor(Sourcem)wherefmapfsrc=src{sourcePull=liftM(fmapf)(sourcePullsrc)}instanceResourcem=>Monoid(Sourcema)wheremempty=Source{sourcePull=returnClosed,sourceClose=return()}mappendab=mconcat[a,b]mconcat[]=memptymconcat(next0:rest0)=srcnext0rest0wheresrcnextrest=Source(pullnextrest)(closenextrest)pullcurrentrest=dores<-sourcePullcurrentcaseresof-- end of the current SourceClosed->docaserestof-- ... and open the next onea:as->pullaas-- no more source, return an EOF[]->returnClosedOpencurrent'val->return(Open(srccurrent'rest)val)closecurrent_rest=do-- we only need to close the current Source, since they are opened-- one at a timesourceClosecurrent