Using unsafePerformIO safely?

It does use IO for other things

Ah, I beg your pardon then, because I was foolish enough to only grep for unsafePerformIO.

I’ll have to adjust my point of view on that slightly.

  1. I agree that the pure ByteString API is much better than doing everything in a BS monad!
  2. I’m somewhat skeptical that much of the ByteString operations really need some form of “unsafely performing” IO. Rather I expect that some very small subset of operations should be exposed by the RTS or a base library and the bytestring library could be purely implemented in terms of those. Just for historical reasons this is done with IO littered all over the place and no one dares clean it up.
  3. The case of bytestring is very different from the case of an SMT solver, largely because there are likely to be fewer calls in one’s codebase to the SMT solver than to the ByteString API, and because there are fewer functions in the SMT solver API.
  4. The SMT solver can easily fail to be pure, for example, by not being installed, or through some OS-specific fault that typical Haskell “pure” functions are isolated from by the RTS.

I strongly suspect that if you use unsafePerformIO for things that you have only informally proved morally pure, i.e. only pure up to some set of observations that you care about, then you will end up with a big headache somewhere down the line.

But ultimately I’m not trying to stop anyone doing so! Everyone is free to choose their own API as far as I am concerned. I’m just trying to offer an alternative and understand the notion that monadic APIs are somehow “complex”. They don’t seem that way to me. And I guess I’m implicitly trying to counter the notion (perhaps) underlying this, that “pure” code is somehow “better” than monadic code.

2 Likes