[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
sub-components:
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