[Haskell-cafe] Re: Lazy IO and closing of file handles

Bryan O'Sullivan bos at serpentine.com
Mon Mar 19 14:32:15 EDT 2007

Pete Kazmier wrote:

> I understand the intent of this code, but I am having a hard time
> understanding the implementation, specifically the combination of
> 'fix', 'flip', and 'interate'.  I looked up 'fix' and I'm unsure how
> one can call 'flip' on a function that takes one argument.

If you look at the code, that's not really what's happening.  See the 
embedded anonymous function below?

 >  flip fix accum $
 >     \iterate accum -> do
 >       ...

It's a function of two arguments.  All "flip" is doing is switching the 
order of the arguments to "fix", in this case for readability.  If you 
were to get rid of the "flip", you'd need to remove the "accum" after 
"fix" and move it after the lambda expression, which would make the 
expression much uglier to write and read.  So all the "flip" is doing 
here is tidying up the code.

(If you're still confused, look at the difference between forM and mapM. 
  The only reason forM exists is readability when you have - in terms of 
the amount of screen space they consume - a big function and a small 
piece of data, just as here.)

As to why it's okay to call "flip" on "fix" at all, look at the types 

fix :: (a -> a) -> a
flip :: (a -> b -> c) -> b -> a -> c

By substitution:

flip fix :: a -> ((a -> b) -> a -> b) -> b

In the case above, accum has type a, and the lambda has type
(a -> IO a) -> a -> IO a, and these fit nicely into the type expected by 
"flip fix".


More information about the Haskell-Cafe mailing list