-- |-- Module : Control.Monad.Stream-- Copyright : Oleg Kiselyov, Sebastian Fischer-- License : BSD3-- -- Maintainer : Sebastian Fischer (sebf@informatik.uni-kiel.de)-- Stability : experimental-- Portability : portable-- -- This Haskell library provides an implementation of the MonadPlus-- type class that enumerates results of a non-deterministic-- computation by interleaving subcomputations in a way that has-- usually much better memory performance than other strategies with-- the same termination properties.-- -- By using supensions in strategic positions, the user can ensure-- that the search does not diverge if there are remaining-- non-deterministic results.-- -- More information is available on the authors website:-- <http://okmij.org/ftp/Computation/monads.html#fair-bt-stream>-- -- Warning: @Stream@ is only a monad when the results of @runStream@-- are interpreted as a multiset, i.e., a valid transformation-- according to the monad laws may change the order of the results.-- moduleControl.Monad.Stream(Stream,suspended,runStream,toList)whereimportControl.MonadimportControl.ApplicativeimportControl.Monad.LogicimportData.FoldableimportData.TraversableimportPreludehiding(foldr)-- |-- Results of non-deterministic computations of type @Stream a@ can be-- enumerated efficiently.-- dataStreama=Nil|Singlea|Consa(Streama)|Susp(Streama)instanceFunctorStreamwherefmap_Nil=Nilfmapf(Singlex)=Single(fx)fmapf(Consxxs)=Cons(fx)(fmapfxs)fmapf(Suspxs)=Susp(fmapfxs)-- |-- Suspensions can be used to ensure fairness.-- suspended::Streama->Streamasuspended=Susp-- |-- The function @runStream@ enumerates the results of a-- non-deterministic computation.-- runStream::Streama->[a]runStream=toList{-# DEPRECATED runStream "use toList" #-}instanceMonadStreamwherereturn=SingleNil>>=_=NilSinglex>>=f=fxConsxxs>>=f=fx`mplus`suspended(xs>>=f)Suspxs>>=f=suspended(xs>>=f)fail_=NilinstanceMonadPlusStreamwheremzero=NilNil`mplus`ys=suspendedys-- suspendingSinglex`mplus`ys=ConsxysConsxxs`mplus`ys=Consx(ys`mplus`xs)-- interleavingxs`mplus`Nil=xsSuspxs`mplus`Singley=ConsyxsSuspxs`mplus`Consyys=Consy(xs`mplus`ys)Suspxs`mplus`Suspys=suspended(xs`mplus`ys)instanceApplicativeStreamwherepure=SingleNil<*>_=NilSinglef<*>xs=fmapfxsConsffs<*>xs=fmapfxs<|>(xs<**>fs)Suspfs<*>xs=suspended(xs<**>fs)instanceAlternativeStreamwhereempty=Nil(<|>)=mplusinstanceMonadLogicStreamwhere(>>-)=(>>=)interleave=mplusmsplitNil=returnNothingmsplit(Singlex)=return$Just(x,Nil)msplit(Consxxs)=return$Just(x,suspendedxs)msplit(Suspxs)=suspended$msplitxsinstanceFoldableStreamwherefoldMap=foldMapDefaultinstanceTraversableStreamwheretraverse_Nil=pureNiltraversef(Singlex)=Single<$>fxtraversef(Consxxs)=Cons<$>fx<*>traversefxstraversef(Suspxs)=Susp<$>traversefxs