module Data.Iteratee.IO.Interact ( ioIter ) where import Control.Monad.IO.Class (MonadIO, liftIO) import Data.Iteratee import qualified Data.Iteratee.Base.StreamChunk as SC -- | Use an IO function to choose what iteratee to run. -- Typically this function handles user interaction and -- returns with a simple iteratee such as 'head' or 'seek'. -- -- The IO function takes a value of type 'a' as input, and -- should return 'Right a' to continue, or 'Left b' -- to terminate. Upon termination, ioIter will return 'Done b'. -- -- The second argument to 'ioIter' is used as the initial input -- to the IO function, and on each successive iteration the -- previously returned value is used as input. Put another way, -- the value of type 'a' is used like a fold accumulator. -- The value of type 'b' is typically some form of control code -- that the application uses to signal the reason for termination. ioIter :: (SC.StreamChunk s el, MonadIO m) => (a -> IO (Either b (IterateeG s el m a))) -> a -> IterateeG s el m b ioIter f a = do i'e <- liftIO $ f a case i'e of Left e -> return e Right i -> do a' <- i ioIter f a'