When implementing certain concurrent systems-level software in Haskell it is good to be aware of all potentially blocking operations. Presently, blocking on an MVar is explicit (it only happens when you do a takeMVar), but blocking on a BLACKHOLE is implicit and can potentially happen anywhere.
If there are known thunks where we, the programmers, know that contention might occur, would it be possible to create a variant of "Control.Monad.Evaluate" that allows us to construct non-blocking software:
evaluate :: a -> IO a evaluateNonblocking :: a -> IO (Maybe a)
It would simply return Nothing if the value is BLACKHOLE'd. Of course it may be helpful to also distinguish the evaluated and unevaluated states. Further, the above simple version allows data-races (it may become blackhole'd right after we evaluate). An extreme version would actively blackhole it to "lock" the thunk... but maybe that's overkill and there are some other good ideas out there.
A mechanism like the proposed should, for example, allow us to consume just as much of a lazy Bytestring as has already been computed by a producer, WITHOUT blocking and waiting on that producer thread, or migrating the producer computation over to our own thread (blowing its cache).