
On Wed, 2008-08-27 at 01:48 +0200, Wolfgang Jeltsch wrote:
Hello,
Haskell is non-strict but not necessarily lazy. So it’s possible that an expression is reduced to WHNF although it is not used yet. Could this “early reduction” also happen to outputs of unsafeInterleaveIO actions (which might trigger the action too early)? While I’d expect those outputs to be evaluated lazily (reduced as late as possible), I cannot find anything in the docs that guarantees this.
In addition, I’d like to know whether unsafeInterleaveIO outputs are guaranteed to be evaluated at most once so that the “interleaved action” is executed at most once. Again, I suppose that this is the case while I cannot find a guarantee for it.
I believe ghc does provide the behaviour you want, almost. I say almost because there is an issue with concurrency. In early versions of ghc's smp implementation it was easy to set up an experiment where two threads would pull on the result of hGetContents and observe different results. This was because different threads could occasionally enter an IO thunk simultaneously. This is now fixed but I understand the fix is not an absolute guarantee. This concurrency difference is the distinction between unsafeInterleaveIO and unsafeDupableInterleaveIO. unsafeDupableInterleaveIO itself is not currently documented but the difference is the same as for unsafeDupablePerformIO which is documented as: This version of 'unsafePerformIO' is slightly more efficient, because it omits the check that the IO is only being performed by a single thread. Hence, when you write 'unsafeDupablePerformIO', there is a possibility that the IO action may be performed multiple times (on a multiprocessor), and you should therefore ensure that it gives the same results each time. Though as I said, the check that the IO is only being performed by a single thread is apparently not an absolute guarantee. The details of why exactly I do not fully understand. If you want a full explanation ask Simon Marlow. Duncan