iteratee Using monad-control in enumerators
Bas van Dijk
v.dijk.bas at gmail.com
Fri Sep 23 13:04:45 BST 2011
Hello,
I would like to propose using controlIO (from monad-control) in the
definition of enumFd and friends.
One of the advantages of using controlIO is that you can use control
operators like allocaBytes which are (far?) more efficient that the
manual mallocBytes and free. Another advantage is that you need fewer
"liftings" of IO actions into 'm' (I only need one controlIO per
iteration of the loop):
---------------------------------------------------------------------
import Control.Monad.IO.Control
type Run s m a = Stream s -> IO (m (Iteratee s m a))
enumFd :: forall s el m a
. (NullPoint s, ReadableChunk s el, MonadControlIO m)
=> Int
-> Fd
-> Enumerator s m a
enumFd bs fd = \iter ->
controlIO $ \runInIO -> do
let bufsize = bs * (sizeOf (undefined :: el))
allocaBytes bufsize $ \p ->
let loop :: Enumerator s m a
loop i = runIter i idoneM onCont
onCont :: (Stream s -> Iteratee s m a)
-> Maybe SomeException
-> m (Iteratee s m a)
onCont _ (Just e) = return $ throwErr e
onCont k Nothing =
controlIO $ \runInIO' -> do
let stop, cont :: Run s m a
stop = return . return . k
cont = runInIO' . loop . k
n <- myfdRead fd (castPtr p)
(fromIntegral bufsize)
case n of
Left _ -> stop $ EOF $ Just
(error "myfdRead failed")
Right 0 -> do yield -- Why is this needed?
stop $ Chunk empty
Right n' -> readFromPtr p (fromIntegral n') >>=
cont . Chunk
in runInIO $ loop iter
---------------------------------------------------------------------
Note that I already use this approach in usb-iteratee[1].
Finally note that this change does not require Iteratee to be an
instance of MonadControlIO.
What do you think?
Bas
[1] http://hackage.haskell.org/package/usb-iteratee
More information about the Iteratee
mailing list