RE: unsafePerformIO around FFI calls

Hal Daume
writes: I'm curious exactly what is "safe" and what is "unsafe" to wrap unsafePerformIO around when it comes to FFI calls.
Here's a simple test:
Could you imagine an alternative implementation of the same API in pure Haskell? (Don't consider efficiency or effort required to write the implementation, just whether it can be done.)
If so, then it is ok to use unsafePerformIO and the ffi to implement the API instead.
If it fails that test, it is incredibly unlikely that it is ok and a proof that it is ok is likely to be pretty complex - maybe worth a PLDI paper or some such.
That's a nice succinct way to describe it. Another way, which boils down to the same thing but which is a little more concrete, is to ask: - Does the function's result depend only on the values of its arguments? (obviously only makes sense for a top-level IO function which you want to wrap in unsafePerformIO - for a non-top-level function or expression just replace 'arguments' with 'arguments and free variables'). Cheers, Simon

That's a nice succinct way to describe it. Another way, which boils down to the same thing but which is a little more concrete, is to ask:
- Does the function's result depend only on the values of its arguments?
I have two problems with this alternative test: 1) It is sometimes slightly stricter test than necessary. Consider a hypothetical pair of C functions Foo toFoo(int); int fromFoo(Foo); which satisfy the property fromFoo(toFoo(x)) == x but such that the result of toFoo does not depend on its argument. (Perhaps toFoo allocates some memory in which to stores its result and returns a pointer to that memory.) The function's result does vary independently of its values so it fails your test. But if toFoo/fromFoo are the only functions on Foo, then we could obviously have implemented the same API in Haskell with the aid of newtype so it passes my test. 2) It fails to recognise the fact that IO actions have side effects. For example, the C library function 'free' always returns the same result (i.e., '()') but it's a bad idea to call free twice on the same argument. One could argue that the side effect is part of the result because IO actions return a modified world but only a long term functional programmer would think like that so it doesn't help the man in the street. (In fact, IIRC, the Concurrent Haskell semantics doesn't use the state-passing explanation so you don't even see side effects reflected as changes in the returned world state.) -- Alastair Reid alastair@reid-consulting-uk.ltd.uk Reid Consulting (UK) Limited http://www.reid-consulting-uk.ltd.uk/alastair/
participants (2)
-
Alastair Reid
-
Simon Marlow