This module provides the Structure
type class, enabling you to
create a pure data structure, which is available immediately, and
then gradually fill it in using the IO
monad. This means that you
can go ahead and start using the structure before it is fully
defined. If a part of the structure is evaluated before it has been
written then that part is treated as _|_
. This is technically more
pure than values from unsafeInterleaveIO
. Evaluating the
structure, even before it is defined, doesn't perform any IO. All
the IO happens in the IO
monad.
Here is an example of creating a list of Int
s and then writing
each level of it step by step. The returned result is [5]
.
foo :: IO [Int] foo = do -- Create the pure list and the handle for writing to it. (pxs, xs) <- newStruc -- Write the cons constructor to the list. This gives us handles -- for writing the head and tail of the list. Just (h, t) <- writeStruc pxs ConsC -- Write the head of the list. writeStruc h 5 -- Write the tail of the list. This finishes it. writeStruc t NilC -- Get rid of the Value wrapper on the list's value and return -- the resulting list. return $ map getValue xs
- class Structure a where
- type Constructor a
- data PStructure a
- type Inner a
- newStruc :: IO (PStructure a, a)
- writeStruc :: PStructure a -> Constructor a -> IO (Inner a)
- writeSoleCon :: (Structure a, Constructor a ~ ()) => PStructure a -> IO (Inner a)
- newtype Value a = Value {
- getValue :: a
- data MaybeC
- data EitherC
- data ListC
Documentation
A structure type is one which represents any lazy data
structure. With the exception of the Value
newtype wrapper, there
is little reason to define an instance of Structure
for completely
strict types. This is because the entire thing must be defined at
once anyway, so you might as well just use a PVar
.
type Constructor a Source
A type representing the structure's constructors by themselves along with any strict data to go along with the head of the structure.
data PStructure a Source
The internal representation of the handle for writing values in IO.
The result type from writing the head of the structure. This is to access deeper levels of the structure.
newStruc :: IO (PStructure a, a)Source
Create a new structure and a handle for writing to it.
writeStruc :: PStructure a -> Constructor a -> IO (Inner a)Source
Write the specified constructor to the given handle and return whatever other handles are necessary to write deeper levels of the structure.
Structure () | |
Structure a => Structure [a] | |
Structure a => Structure (Maybe a) | |
Structure (Value a) | |
(Structure a, Structure b) => Structure (Either a b) | |
(Structure a, Structure b) => Structure (a, b) | |
(Structure a, Structure b, Structure c) => Structure (a, b, c) | |
(Structure a, Structure b, Structure c, Structure d) => Structure (a, b, c, d) | |
(Structure a, Structure b, Structure c, Structure d, Structure e) => Structure (a, b, c, d, e) | |
(Structure a, Structure b, Structure c, Structure d, Structure e, Structure f) => Structure (a, b, c, d, e, f) |
writeSoleCon :: (Structure a, Constructor a ~ ()) => PStructure a -> IO (Inner a)Source
Write the constructor for a structure with only one possible
structure, assuming that the Constructor
type for that type is
().