ANN: H98 FFI Addendum 1.0, Release Candidate 10

Ross Paterson ross@soi.city.ac.uk
Wed, 4 Jun 2003 17:54:22 +0100


On Wed, Jun 04, 2003 at 11:18:59PM +1000, Manuel M T Chakravarty wrote:
> [quoted description of unsafePerformIO]
> I think, the warning sign is clear.  Especially in the
> context of the FFI, anything more is a waste of paper IMHO.
> After all, you can import any C function with a pure type,
> which also allows you to wreck arbitrary havoc.  We enable
> the user to disguise arbitrary machine code as a Haskell
> function of essentially arbitrary type.  In comparison,
> `unsafePerformIO' seems angelic.

Certainly the FFI enhances Haskell with the ability to shoot one's foot off.
The aim isn't to prevent that, but to offer clear guidance to help programmers
retain their feet, as well as various desirable properties of Haskell.
And indeed the spec does say in several places "it's your responsibility
to ensure such-and-such, and if not the results are undefined".  So I'm
going to propose some changes in wording:

In 3.3, after the sin example, add:

+ Such a declaration asserts that the external entity is a true function,
+ i.e. when applied to the same argument values it always produces the
+ same result.

In 5.1, change:

- Furthermore, \code{Foreign} provides the following function:
---
+ Sometimes an external entity is a pure function, except that it passes
+ arguments and/or results via pointers.  To permit the packaging of
+ such entities as pure functions, \code{Foreign} provides the following
+ primitive:

Rationale: it's not a function, and this wording limits its purpose.

- \item[unsafePerformIO ::\ IO a -> a] Execute an \code{IO} action in place of a
- pure computations.  For the behaviour to be predictable, the IO computation
- should be free of side effects and independent of its environment.
---
+ \item[unsafePerformIO ::\ IO a -> a]
+ Return the value resulting from executing the \code{IO} action.
+ This value should be independent of the environment;
+ otherwise, the system behaviour is undefined.

Rationale: to preserve equational reasoning, the crucial responsibility
of the programmer is to ensure that the action is deterministic.  Without
that, all bets are off.  The next paragraph deals with side effects:

  If the \code{IO} computation wrapped in \code{unsafePerformIO} performs side
  effects, then the relative order in which those side effects take place
  (relative to the main \code{IO} trunk, or other calls to
  \code{unsafePerformIO}) is indeterminate.

Having washed our hands of unsafePerformIO applied to non-deterministic
actions, we no longer need the third paragraph, which (though scary)
provides no useful guidance:

- Great care should be exercised in the use of this function.  Not only
- because of the danger of introducing side effects, but also because
- \code{unsafePerformIO} may compromise typing, for example, when it is used
- in conjunction with polymorphic references.