Gabriella439 / Haskell-Pipes-Safe-Library

Safety for the pipes ecosystem
BSD 3-Clause "New" or "Revised" License
26 stars 21 forks source link

Each await/yield (Request/Respond constructors) inside a pipe unmask operation results in switching to a new mask/unmask pair in the base monad. This means the current unmask operation must be retrieved for each new block of wrapped base monad operations (M constructors) inside a pipe unmask. The current code doesn't do this. #15

Closed twhitehead closed 10 years ago

twhitehead commented 10 years ago

Here is some code that demonstrates this by tracking the mask/unmask operations paris in the base monad via StateT and printing out which is which. The core of the code is

trace :: MonadIO m => String -> m a -> m a
trace m ia = do
  liftIO (putStrLn ("begin " ++ m))
  a <- ia
  liftIO (putStrLn ("end   " ++ m))
  return a

examplep :: (MonadIO m, MonadCatch m) => (forall q. Producer () m q -> Producer () m q) -> Producer () m ()
examplep unmask =
  trace "Proxy  unmask" $
    unmask $ trace "yield (output functions as original two IO calls)" $ yield ()

devnullp :: Monad m => Consumer a m ()
devnullp = await >> devnullp

main :: IO ()
main = evalTraceT . runEffect $
         trace "Proxy  mask" $
           mask examplep >-> devnullp

and running it shows the incorrect use of the original unmask operation inside the subsequent mask operation following the yield

begin Proxy  mask
begin StateT mask   0
begin Proxy  unmask
begin StateT unmask 0
begin yield (output functions as original two IO calls)
end   StateT unmask 0
end   StateT mask   0
begin StateT mask   1
begin StateT unmask 0
end   yield (output functions as original two IO calls)
end   StateT unmask 0
begin StateT unmask 0
end   StateT unmask 0
end   Proxy  unmask
end   StateT mask   1
end   Proxy  mask
Gabriella439 commented 10 years ago

I will close this since I assume this was fixed by pull request #16. If not, then just reopen the issue.