FixIO/ Tackling Awkward Squad

Levent Erkok erkok@cse.ogi.edu
Fri, 16 Feb 2001 09:51:03 -0800


Marcin 'Qrczak' Kowalczyk wrote:
> 
> Fri, 16 Feb 2001 04:14:26 -0800, Simon Peyton-Jones <simonpj@microsoft.com> pisze:
> 
> > fixIO m = do { v <- newEmptyMVar
> >                ; result <- m (unsafePerformIO (takeMVar v))
> >                ; putMVar v result
> >                ; return result }
> 
> If we have unsafePerformIO, why not this?
> 
> fixIO m = let x = unsafePerformIO (m x) in return $! x

Why the strict application?

You probably want:

 do { fixIO (\x -> return (x+1)); return 2 }

to evaluate to (return 2). But the version with strict application
diverges.

By the way, we can prove that it should evaluate to (return 2) using the
monadic-fixpoint axiomatization:

  do { fixIO (\x -> return (x+1)); return 2 }
= {expand do}
  fixIO (\x -> return (x+1)) >>= \_ -> return 2
= {rewrite}
  fixIO (return . (+1)) >>= \_ -> return 2
= {mfix (return . h) = return (fix h), mfix = fixIO for the IO monad}
  return (fix (+1)) >>= \_ -> return 2
= {return x >>= f = f x}
  return 2

So, it looks like:

  fixIO m = let x = unsafePerformIO (m x) in return x

will do a better job.

-Levent.