iteratee-0.3.6: src/Data/Iteratee/IO/Interact.hs
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'