An Alternative view of I/O programs, popular in earlier lazy functional programming languages, was to see the input and output as Strings, that is as lists of characters. Under that model an I/O program is a function

listIOprog :: Str->Str

This obviously makes sense in a 'batch' program, where al, the input is read before any output is produced but in fact it also works for interactive programs where input and output are interleaved, if the language is lazy. This is because in a lazy language we can began to print the result of a computation - the output of the interactive program here - before the arguement - the interactive input - is fully evaluated. As an example, repeadtely to rever lines of input under this model one can write

listIOprogram = unlines. map reverse . lines

I don't understand the bolded line. How can we evaluate the output before the actual inputs are given? For eg, take the function Sum x y = x+y, what would it mean to evaluate this without any numbers are given.


1 Answer 1


Addition is not a good example for this because it does need both of its inputs. Laziness comes into play for functions whose output may not depend on all of the input.

An example of laziness that can be found in virtually all mainstream programming languages is the boolean operator && (and its sibling ||). Conventionally, X && Y first evaluates the expression X, then if X is true, it evaluates Y. But if X is false, it skips evaluating Y, ignoring any of its side effects.

Lazy evaluation of the following program will interleave input (read_bool) and output (write_bool):

let x = read_bool() in
let y = read_bool() in
write_bool(x && y);

Lazy evaluation follows demand: we do not evaluate read_bool() immediately when we encounter the binding x = read_bool(), because x might not be needed in the end. Instead, write_bool is the operation that drives evaluation, because the value must be known before write_bool can print it.

The evaluation of that expression can be broken down as follows, with IO operations written in bold.

  1. write_bool(x && y) demands x && y
  2. x && y demands x
  3. x = read_bool() reads a boolean. For example, x = false. Now we can go back to the previous expression that demanded x.
  4. false && y = false (by definition of &&).
  5. write_bool(false) writes false.
  6. write_bool(y) demands y
  7. y = read_bool() reads a boolean. For example, y = true.
  8. write_bool(true) writes true.

That is how lazy evaluation lets us interleave IO operations even though in the source expression, all input operations appeared before all output operations.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.