-- | A monad transformer for the [partial] consumption of 'List's.-- The interface closely mimics iterators in languages such as Python.---- It is often nicer to avoid using Consumer and to use-- folds and higher-order functions instead.moduleControl.Monad.Consumer(ConsumerT,evalConsumerT,next,consumeRestM)whereimportControl.Applicative(Applicative(..))importControl.Monad(MonadPlus(..),ap)importControl.Monad.ListT(ListT(..),ListItem(..))importControl.Monad.Maybe(MaybeT(..))importControl.Monad.State(StateT,evalStateT,get,put)importControl.Monad.Trans(MonadTrans(..),MonadIO(..))importData.List.Class(List(..))importData.Maybe(fromMaybe)-- | A monad tranformer for consuming 'List's.newtypeConsumerTvma=ConsumerT{runConsumerT::StateT(Maybe(ListTmv))ma}instanceMonadm=>Functor(ConsumerTvm)wherefmapf=ConsumerT.fmapf.runConsumerTinstanceMonadm=>Monad(ConsumerTvm)wherereturn=ConsumerT.returnfail=ConsumerT.faila>>=b=ConsumerT$runConsumerTa>>=runConsumerT.binstanceMonadm=>Applicative(ConsumerTvm)wherepure=return(<*>)=apinstanceMonadTrans(ConsumerTv)wherelift=ConsumerT.liftinstanceMonadIOm=>MonadIO(ConsumerTvm)whereliftIO=lift.liftIO-- | Consume a 'ListT'evalConsumerT::Listl=>ConsumerTv(ItemMl)a->lv->ItemMlaevalConsumerT(ConsumerTi)=evalStateTi.Just.toListT-- Consumer no longer has a producer left...putNoProducer::Listl=>StateT(Maybe(lv))(ItemMl)()putNoProducer=putNothing-- | Consume/get the next valuenext::Monadm=>ConsumerTvm(Maybev)next=ConsumerT.runMaybeT$dolist<-MaybeTgetitem<-lift.lift$runListTlistcaseitemofNil->doliftputNoProducermzeroConsxxs->doputProducerxsreturnxwhereputProducer=put.Just-- | Return an instance of the underlying monad that will use the given 'ConsumerT' to consume the remaining values.-- After this action there are no more items to consume (they belong to the given ConsumerT now)consumeRestM::Monadm=>ConsumerTamb->ConsumerTam(mb)consumeRestMconsume=ConsumerT$domRest<-getletrest=fromMaybemzeromRestputNoProducerreturn$evalConsumerTconsumerest