On 27 Apr 2000, Marcin 'Qrczak' Kowalczyk wrote:
> Unless we are talking about unsafe extensions, which OTOH are very
> useful too. Sometimes eliminating unsafePerformIO would require
> huge rewrite of the whole program, making it less readable and less
> efficient. But they should be clearly marked as unsafe. The safe
> sublanguage should behave safely.
Changing a course a little bit to describe some dangers
related to usage of `unsafePerformIO'....
I am not very proud of what I did, but I will tell this
story anyway, hoping that someone can learn from my mistake.
"Unsafe perform" is just what it says :-)
When writing DateTime module few days ago I stupidly
entered this line of code, without even thinking about
its signature:
currentSecond = second $ unsafePerformIO localDateTime
where `localDateTime' has been defined via primitive
call to C:
localDateTime :: IO DateTime
To my distress the clock stopped after the first call to
`currentSecond'. I took me much more than just few seconds
to realize that the problem was not related to any
bug in the C code, but in the signature of
`currentSecond':
currentSecond :: Int
This is all fine and dandy if `currentSecond' is within `where'
clause, because it will be always evaluated afresh.
But being a top level function, as it was, it was always
reporting a cached value. This all relates to the yesterday's
subject "openFile :: String -> String" but it is even more
spectacular in its side effect. Try to beat this!
Jan