[Haskell-cafe] Takusen and strictness

Bulat Ziganshin bulat.ziganshin at gmail.com
Fri Mar 2 17:38:11 EST 2007

Hello Alistair,

Friday, March 2, 2007, 5:48:17 PM, you wrote:
> sure if it would be possible. I don't really understand how getContents
> works; is there any advice or guidelines as to how to use (or abuse)
> unsafeInterleaveIO? Some googling has found:

i think i can explain this dark side of IO :)

one can use unsafePerformIO (not unsafeInterleaveIO) to perform i/o
operations noy in predefined order but by demand. for example, the
following code:

do let c = unsafePerformIO getChar
   do_proc c

will perform getChar i/o call only when value of c is really required
by code, i.e. it this call will be performed lazily as any usual
Haskell computation

now imagine the following code:

do let s = [unsafePerformIO getChar, unsafePerformIO getChar, unsafePerformIO getChar]
   do_proc s

three chars inside this list will be computed on demand too, and this
means that their values will depend on the order they are consumed. it
is not that we usually need :)

unsafeInterleaveIO solves this problem - it performs i/o only on
demand but allows to define exact *internal* execution order for parts
of your datastructure. it is why i wrote that unsafeInterleaveIO makes
illegal copy of button :)

first, unsafeInterleaveIO has (IO a) action as a parameter and returns
value of type 'a':

do str <- unsafeInterleaveIO myGetContents

second, unsafeInterleaveIO don't perform any action immediately, it
only creates a box of type 'a' which on requesting this value will
perform action specified as a parameter

third, this action by itself may compute the whole value immediately
or... use unsafeInterleaveIO again to defer calculation of some

myGetContents = do
   c <- getChar
   s <- unsafeInterleaveIO myGetContents
   return (c:s)

this code will be executed only at the moment when value of str is
really demanded. in this moment, getChar will be performed (with
result assigned to c) and one more lazy IO box will be created - for s.
this box again contains link to the myGetContents call

then, list cell returned that contains one char read and link to
myGetContents call as a way to compute rest of the list. only at the
moment when next value in list required, this operation will be
performed again

as a final result, we get inability to read second char in list before
first one, but lazy character of reading in whole. bingo!

ps: of course, actual code should include EOF checking. also note that
you can read many chars/records at each call:

myGetContents = do
   c <- replicateM 512 getChar
   s <- unsafeInterleaveIO myGetContents
   return (c++s)

Best regards,
 Bulat                            mailto:Bulat.Ziganshin at gmail.com

More information about the Haskell-Cafe mailing list