On Thu, 1 Jan 2009, Brandon S. Allbery KF8NH wrote:

On 2009 Jan 1, at 16:44, Henning Thielemann wrote:
If it is generally possible to use unsafeInterleaveIO such that it
executes actions in the right order, wouldn't this allow the definition
of a general lazy IO monad?

I thought unsafeInterleaveIO and users of it (readFile, hGetContents) didn't guarantee the order of actions relative to independent IO actions (that is, those performed outside the unsafeInterleaveIO) and this was why it is generally disrecommended. For example the recurring situation where people try to readFile f >>= writeFile . someTransform and the writeFile fails with a "file locked" exception.

Sure, it's dangerous. But for what I want to do, this situation cannot occur. I can come up with a simple example which might be generalized. It simulates what hGetContents does.

liftLazy2 :: (a -> b -> c) -> IO a -> IO b -> IO c
liftLazy2 f x y =
   fmap (\ ~(xr, ~(yr,())) -> f xr yr) $
   unsafeInterleaveIO $ liftM2 (,) x $
   unsafeInterleaveIO $ liftM2 (,) y $
   return ()

test0, test1 :: IO String
test0 = liftLazy2 (const)      getLine getLine
test1 = liftLazy2 (flip const) getLine getLine


test0 only requests the first line,
test1 expects two lines as user input.

However, with liftLazy2 we have only Applicative functionality, not Monad, and it is not composable.

For example:
  fmap (\((x,y),z) -> z) $ liftLazy2A (,) (liftLazy2A (,) getLine getLine) 
getLine

This requests only one line, but should three ones. The reason is that the first two getLines are defered even until the last one. Thus, it is not enough that liftLazy2 returns (IO c). Instead it must return (IO (c,(a,(b,())))) and these pair emulated lists must somehow be combined in order to preserve the order of execution. This looks somehow like a writer monad transformer.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to