I apologize for the delay. Right now I'm going through a large backlog
of things that I delayed while completing my dissertation.
I will comment inline below:
On 11/28/2013 2:06 PM, Tyson Whitehead wrote:
I've been implementing the pipes internals based on their description
to learn more about them (nice framework BTW). I'm currently working
through the pipe-safe routines and have run into an issue where I
can't see how liftMask is correct as currently implemented
http://lpaste.net/96356
In more details, in something like (runEffect $ mask examplep), where
example is
examplep :: (MonadIO m, MonadCatch m) => (forall q. Proxy a' a b' ()
m q -> Proxy a' a b' () m q) -> Proxy a' a b' () m ()
examplep unmask = do
unmask do
liftIO $ putStrLn "IO Action 1"
yield ()
liftIO $ putStrLn "IO Action 2"
return ()
mask returns multiple IO actions that are run in runEffect. This
means that each lifted IO operation will potentially have it's own
unique unmask operation. The mask code, however, captures the first
unmask operation in a closure and then uses it for all subsequent
operations (i.e., "IO Action 2" is unmasked using "IO Action 1"'s
unmask operation instead of its own).
That is, in (runEffect $ mask examplep)
1 - each group of IO actions becomes embedded it their own underlying
IO mask operation inside of Proxy's mask,
2 - this underlying IO mask operation stashes the associated IO
unmask function in the IORef inside of Proxy's mask, and
3 - the passed Proxy unmask retrieves this and uses unsafeHoist to
push it through to all further IO actions.
The thing I'm having problems with is that, if there are any more
interleaving Request or Respond operations (such as the above yield),
then subsequent IO operations are going to be running in a different
IO mask operation with a potentially different unmask operation. I
would think a correct implementation would have to re-read the IORef
for each group of IO actions as the associated IO unmask may have changed.
It does. The internal `unmask` function in the implementation of
`liftMask` re-reads the `IORef` to retrieve the most recent unmasking
function. This means that every time your `examplep` proxy calls
`unmask` it is always getting the latest unmasking function and not just
the first one. To clarify things further, let's assume that you write
something like this:
mask $ \restore -> do
io1
restore io2
io3
yield ()
io4
restore io5
io6
This will generate two internal `mask` calls, one of which brackets
`io1` through `io3` and one of which brackets `io4` through `io6`. The
first call to `restore` will use the unmasking function corresponding to
the first internal `mask` call and the second call to `restore` will use
the unmasking function corresponding to the second internal `mask` call.
Am I missing something here or is this a bug?
Cheers! -Tyson
--
You received this message because you are subscribed to the Google
Groups "Haskell Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to [email protected].
To post to this group, send email to [email protected].
--
You received this message because you are subscribed to the Google Groups "Haskell
Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].