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

  



Reply via email to