Our first example runs in a very simple setting: a computing environment where the interaction between the external world and the program is through a keyboard and a text screen. The user provides input using the keyboard and the program prints output on the screen.
We consider a reactive program, where the user input is just echoed on the screen, line by line, by the program. This trivial interaction, the "Hello, world" of reactive programs, goes on indefinitely.
Here is the program:
module Echo where import POSIX echo env = class handler str = action env.stdout.write str result handler root world = do env = new posix world handler = new echo env env.stdin.installR handler
Let us explain the program:
The root procedure is special in that it will be invoked by the run-time system during startup of the corresponding Timber program. Its type signature must be
root :: World -> Cmd () ()
where World is a primitive abstract type denoting a link to the real external world, and Cmd () () is the type of procedures running in an empty state, returning no result. The name root is by no means mandatory for a root procedure, but if no explicit root name is provided when a Timber executable is built, root will be used as a default.
After program startup and execution of the root procedure, the program will be idle, waiting for user input on the stdin stream. When such (line-buffered) input occurs, the runtime system invokes the installed handler method, with the input line as argument. This trivial program is typical for the Timber programming idiom; we describe how the program should react to external events and install, or register, this description with the external world.
We remark, finally, that module POSIX declares its operating system environment as a record type Env, and that the use of stdout and stdin is consistent with their types as specified in Env: