[Haskell-cafe] unsafeInterleaveIO respecting order of actions

Henning Thielemann lemming at henning-thielemann.de
Sat Jan 3 05:31:09 EST 2009


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.


More information about the Haskell-Cafe mailing list