rec-def-0.2: Recursively defined values

System.IO.RecThunk

Description

The Thunk API provides a way to defer potentially recursive computations:

• thunk is lazy in its argument, and does not run it directly
• the first force triggers execution of the action passed to thunk
• that action is run at most once, and returns a list of other thunks
• force forces these thunks as well, and does not return before all of them have executed
• Cycles are allowed: The action passed to thunk may return a thunk whose action returns the first thunk.

The implementation is hopefully thread safe: Even if multiple threads force or kick related thunks, all actions are still run at most once, and all calls to force terminate (no deadlock).

>>> :set -XRecursiveDo
>>> :{
  mdo t1 <- thunk $putStrLn "Hello" >> pure [t1, t2] t2 <- thunk$ putStrLn "World" >> pure [t1, t2]
putStrLn "Nothing happened so far, but now:"
force t1
putStrLn "No more will happen now:"
force t1
putStrLn "That's it"
:}
Nothing happened so far, but now:
Hello
World
No more will happen now:
That's it

Synopsis

# Documentation

data Thunk Source #

An IO action that is to be run at most once

thunk :: IO [Thunk] -> IO Thunk Source #

Create a new Thunk from an IO action.

The IO action may return other thunks that should be forced together whenver this thunk is forced (in arbitrary order)

A Thunk that that already is done.

Equivalent to do {t <- thunk (pure []); force t; pure t }

force :: Thunk -> IO () Source #

Force the execution of the thunk. If it has been forced already, it will do nothing. Else it will run the action passed to thunk, force thunks returned by that action, and not return until all of them are forced.