[Haskell-beginners] Re: [Haskell-cafe] Just how unsafe is unsafe

Jonathan Cast jonathanccast at fastmail.fm
Thu Feb 5 16:33:13 EST 2009

On Thu, 2009-02-05 at 16:11 -0500, Andrew Wagner wrote:
> So we all know the age-old rule of thumb, that unsafeXXX is simply
> evil and anybody that uses it should be shot (except when it's ok). 

> I understand that unsafeXXX allows impurity, which defiles our ability
> to reason logically about haskell programs like we would like to.

Not just that!  Parametric polymorphism is unsound in combination with
mutable values; but unsafePerformIO turns on exactly that combination.

unsafeCoerce :: alpha -> beta
unsafeCoerce x = unsafePerformIO $ do
  let r = unsafePerformIO $ newIORef undefined
  r `writeIORef` x
  readIORef r

> My question is, to what extent is this true? 

unsafePerformIO is a true function --- in the absence of any fancy
compiler trickery --- on a small subset of its domain.  Outside of that
subset, I would regard use of unsafePerformIO simply as a bug ---
violation of an unchecked precondition.  Period.

> Suppose we had a module, UnsafeRandoms, which had a function that
> would allow you to generate a different random number every time you
> call it.

unsafePerformIO does not allow you to guarantee this!  If I defined

  myRandomNumber = unsafePerformIO $ randomNumber

then the compiler is permitted to call randomNumber (at most) *once*,
and use that number throughout the program.

> The semantics are relatively well-defined,

Leaving aside the issue above, I would think complete randomness was
nearly the worst possible case, semantically.  (The *worst* worst
possible case would be non-statistical non-determinism --- which is what
you actually get here).

> impurity is safely sectioned off in its own impure module, which is
> clearly labeled as such. How much damage does this do?

Well, it forces me to chase your libraries import lists to decide
whether I want to trust your code, for one thing.  Haskell is all about
making it easier to audit code, not harder.

> Can we push the lines elsewhere?

I'd rather not.

> Is sectioning unsafeXXX into Unsafe modules a useful idiom that we can
> use for other things as well?

I'd rather not write other unsafe functions at all.  Sectioning off
things that need to be unsafe into pure solutions --- like, say, monads
--- is a much better idea.  (Go read the global variables thread from
last year).


More information about the Beginners mailing list