sink-0.1.0.1: An alternative to lazy I/O that doesn't conflate execution with evaluation

Data.Sink

Description

Sinks are a more flexible alternative to lazy I/O (unsafeInterleaveIO). Lazy I/O conflates evaluation with execution; a value obtained from unsafeInterleaveIO can perform side-effects during the evaluation of pure code. Like lazy I/O, a Sink provides a way to obtain the value of the result of an IO action before the action has been executed, but unlike lazy I/O, it does not enable pure code to perform side-effects. Instead, the value is explicitly assigned by a later IO action; repeated attempts to assign the value of a Sink fail. The catch is that this explicit assignment must occur before the value is forced, so just like with lazy I/O, you can't get away with completely ignoring evaluation order without introducing bugs. However, violating this condition does not violate purity because if the value is forced before it has been assigned, it is .

In practice, using Sinks instead of unsafeInterleaveIO requires a bit more IO boilerplate. The main practical difference is that while unsafeInterleaveIO requires you to reason about effects from the point of view of pure code, Sinks require you to reason about evaluation order of pure code from the point of view of IO; the IO portion of your program will have to be aware of what data is necessary to produce *for* your pure code in order to be able to consume the output it expects *from* your pure code.

Synopsis

Documentation

data Sink a Source

A write-once reference

Instances

newSinkMsg :: String -> IO (Sink a, a)Source

Create a new Sink and a pure value. If you force the value before writing to the Sink, the value is . If you write to the Sink before forcing the value, the value will be whatever you wrote to the Sink. The String argument is an error message in case you force the value before writing to the Sink.

newSink :: IO (Sink a, a)Source

Create a new Sink with a default error message.

tryWriteSink :: Sink a -> a -> IO BoolSource

Attempt to assign a value to a Sink. If the Sink was previously unwritten, write the value and return True, otherwise keep the old value and return False. This is an atomic (thread safe) operation.

writeSink :: Sink a -> a -> IO ()Source

Attempt to assign a value to a Sink. If the Sink had already been written to, throw a MultipleWrites exception. This is an atomic (thread safe) operation.

data MultipleWrites Source

An exception that is thrown by writeSink if you attempt to write to a Sink more than once.

Constructors

MultipleWrites