unsafePerformIO around FFI calls

Simon Marlow simonmar@microsoft.com
Tue, 9 Jul 2002 16:03:18 +0100


> > 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:
>=20
> >   - Does the function's result depend only on the values of its
> > arguments?
>=20
> I have two problems with this alternative test:
>=20
> 1) It is sometimes slightly stricter test than necessary.
>=20
>    Consider a hypothetical pair of C functions
>   =20
>      Foo toFoo(int);
>      int fromFoo(Foo);
>   =20
>    which satisfy the property
>   =20
>      fromFoo(toFoo(x)) =3D=3D x
>   =20
>    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.)
>   =20
>    The function's result does vary independently of its values so it
>    fails your test.
>   =20
>    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.

Ok, if we're going to nit pick :)  When talking about equality you have
to restrict that to "observable equivalence" in the context of whatever
abstract types you're dealing with.  If a function always returns
observably equivalent results when given observably equivalent
arguments, then it is "safe".

For example, toFoo would not be safe if you can test for equality
between pointers.  But if all you can do is convert it back using
fromFoo, then you're ok.

> 2) It fails to recognise the fact that IO actions have side effects.

Well, side effects are usually only visible in the IO monad so that's
ok.  In your free() example, the result is either () or _|_, so the
function does depend on more than just the value of the argument.  I
think the definition holds (but only just).

For example, we normally consider a function which uses some temporary
allocation on the C heap as "safe" to use from unsafePerformIO.  But its
side effect is visible from the IO monad by inspecting the C heap
pointer.

Cheers,
	Simon