7

I have been reading about unsafePerformIO lately, and I would like to ask you something. I'm OK with the fact that a real language should be able to interact with the external environment, so unsafePerformIO is somewhat justified.

However, at the best of my knowledge, I'm not aware of any quick way to know whether an apparently pure (judging from the types) interface/library is really pure without inspecting the code in search for calls to unsafePerformIO (documentation could omit to mention it). I know it should be used only when you're sure that referential transparency is guaranteed, but I would like to know about it nevertheless.

Riccardo T.
  • 8,907
  • 5
  • 38
  • 78
  • 3
    "I know it should be used only when you're sure that referential transparency is guaranteed" exactly. In should only be used when the internal operations can't leak to the outside in any reasonable way, i.e. when there is no way to tell there's any such stuff going on under the hood. – leftaroundabout Apr 04 '12 at 22:38
  • 1
    By the way, using `unsafePerformIO` to interact with the external environment is exactly what you're *not* allowed to do. All the effects are supposed to be internal to your code — things like using a mutable variable behind the scenes to implement memoisation. – ehird Apr 04 '12 at 23:04
  • @ehird: Thanks for the further explanation, but when I wrote "environment" I meant it in the wider possible meaning, which includes external (non-haskell) libraries also. I didn't think about user interaction. – Riccardo T. Apr 04 '12 at 23:09

2 Answers2

10

There's no way without checking the source code. But that isn't too difficult, as Haddock gives a nice link directly to syntax-highlighted definitions right in the documentation. See the "Source" links to the right of the definitions on this page for an example.

Safe Haskell is relevant here; it's used to compile Haskell code in situations where you want to disallow usage of unsafe functionality. If a module uses an unsafe module (such as System.IO.Unsafe) and isn't specifically marked as Trustworthy, it'll inherit its unsafe status. But modules that use unsafePerformIO will generally be using it safely, and thus declare themselves Trustworthy.

ehird
  • 40,602
  • 3
  • 180
  • 182
  • Thank you, so it is just as I thought... source code or nothing. Well at least, though guaranteed again by the programmer, Safe Haskell may help in automatically identifying some unsafe modules. – Riccardo T. Apr 04 '12 at 22:54
5

In the case that you're thinking, the use of unsafePerformIO is unjustified. The documentation for unsafePerformIO explains this: it's only meant for cases where the implementer can prove that there is no way of breaking referential transparency, i.e., "purely functional" semantics. I.e., if anybody uses unsafePerformIO in a way that a purely functional program can detect it (e.g., write a function whose result depends on more than just its arguments), then that is a disallowed usage.

If you ran into a such a case, the most likely possibility is that you've found a bug.

Luis Casillas
  • 29,802
  • 7
  • 49
  • 102
  • 2
    From the question: "I know it should be used only when you're sure that referential transparency is guaranteed, but I would like to know about it nevertheless." – ehird Apr 04 '12 at 22:43
  • @sacundium: You're right, I already saw the documentation page for `unsafePerformIO` but that's only a rule, and I can't be possibly sure that the programmer actually has a proof for referential transparency :) – Riccardo T. Apr 04 '12 at 22:44