i-Tasks

-

Generating Multi-User Workflow Systems for the WWWeb

With Clean’s new i-Tasks library you can generate a multi-user workflow system for the web.

It makes use of the i-Data library with which web forms can be generated and handled automatically given a static type of a data structure.

These Clean libraries use generic programming techniques which enables a very compact and concise notation.

DOWNLOAD INSTRUCTIONS

If you want to use i-Tasks you

- need to download the latest Clean compiler for Windows;
- and download the latest i-Tasks library. And please do read the enclosed Read-Me !
  Current Version i-Tasks library: 0.92. Date: Sunday, 17 June 2007. © 2006 – 2007 Rinus Plasmeijer

More information:

- read the papers explaining i-Tasks and i-Data,
- for a short introduction into i-Tasks have a look at this power-point presentation.

Have a look at the DEMO’s and the corresponding CLEAN CODE:

- Surf to the DEMO page.

Below we give a short idea about what i-Tasks are. More examples are given in the DEMO page.

i-Tasks: generating an editor for any (first order) type

Here follows the code of a complete i-Tasks application written in Clean:

module example

import StdEnv, iTasks

Start :: *World -> *World

Start world = doHtmlServer (singleUserTask 0 True simple) world

simple :: (Task Int)
simple = editTask "Done" createDefault

The first line defines the module name; the second imports the standard environment and the i-Tasks library. The third line is Clean’s main function Start. It automatically links in an http server (doHtmlServer) for easy testing of a user defined web application. The task to do is defined by the function simple. This function uses the basic i-Tasks editor editTask. It can generate an html form editor for any type. The editor does need an initial value of this type. In this case a default value (0) is generated by createDefault. The function createDefault can create a default value for any first order type. With the button "Done" the user can indicate that the i-Task editor is finished. This example generates the following web page in which repeatedly an Integer value can be typed in until the "Done" button is pressed.

Only Integer values will be accepted by the application, because the type of simple is (Task Int). By only changing the type of the function simple a different form will be generated, e.g. if the type is changed into (Task (Int, Real)) one obtains a box for typing in an Integer and a Real value:

simple :: (Task (Int, Real))
simple = editTask "Done" createDefault

This works for any first order type one can define in Clean (algebraic data types such as lists, trees, for types like arrays and records), hence for user defined types as well. For instance for record types:

:: Person = { name :: String

, street :: String

, number :: Int

, zipCode :: String

, town :: String

, born :: HtmlDate

}

simple :: (Task Person)

simple = editTask "Done" createDefault

derive gForm Person; derive gUpd Person; derive gParse Person; derive gPrint Person; derive gerda Person;

For a user defined type one has to ask the compiler to derive instances for the generic functions that are being used to generate, store and handle web forms:

- gForm: creates an html form for any first order type
- gUpd: can handle any change made in such a form
- gParse and gPrint are used for serialization
- gerda: is an option enabling to automatically store and retrieve values of any type in a relational database

i-Tasks: combining tasks

Monads are used (yes, we have them in Clean, and they are type safe thanks to Clean’s uniqueness typing) for sequencing i-Tasks. For instance if one want to type in two Integers in a sequence and add up their values, one defines:

simple :: (Task Int)

simple

= editTask "Done" createDefault

=>> \v1 -> editTask "Done" createDefault

=>> \v2 -> [Txt "+", Hr [] ]

!>> return_D (v1 + v2)

First an integer value is asked from the user returning the value v1, then another one is asked returning the value v2, then some html code is printed [Txt "+", Hr [] ] and the sum of these two values is returned and printed return_D (v1 + v2). Notice that the code of an i-Tasks application is very easy to read, certainly for functional programmers. The reason is the following. Although the application is started from scratch every time a new event is received from the client, it remembers its state and finds its way back to the point where it was handling tasks the previous time. So the programmer can read the code “line by line” although it is not executed in this way at all. The application remembers which tasks are finished and which tasks still have to be done. Another reason for the simplicity of the code is that almost all information is saved and retrieved automatically. Information can be stored in html pages, in files or in a relational database just by changing an option.

The library offers many combinators for handling tasks, such as:

- sequencing of tasks
- repeating tasks
- choose 1 task out of n
- choose n tasks out of n (multiple choice)
- orTasks: do n tasks in any order, but finish as soon as one of the tasks completes
- andTasks: do n tasks in any order, and finish when all of the tasks are completed

In fact, all workflow patterns as they are commonly can be found in commercial workflow systems are supported.

But there are many advantages over many commercial systems.

- Tasks are statically typed.
- Tasks are fully dynamic: what a task is doing may depend on the work produced.
- One can define user defined tasks.
- Tasks can be defined recursively.
- Thanks to polymorphism and overloading user defined re-useable tasks can be defined.
- Tasks are fully compositional: any combination of tasks made with the combinators can be re-used again as a task.
- Tasks can be higher order: not only values can flow from one task to another, but it can be tasks!

To see more complicated examples: goto the demo page.

i-Tasks: multi-user tasks

Tasks can be assigned to different users. Each user has a unique id. This id can be assigned (@::) to any task or any combination of tasks. For instance in our simple example we can specify that the first number has to be given by user 1, the second by user 2, the result is shown to the default user (which is user 0).

simple :: (Task Int)

simple

= 1 @:: editTask "Done" createDefault

=>> \v1 -> 2 @:: editTask "Done" createDefault

=>> \v2 -> [Txt "+", Hr [] ]

!>> return_D (v1 + v2)

So, all participants in an i-Task workflow application work with one and the same application. This makes it relatively easy to reason about the system. The system can deal with multiple users and will show to each user only the part of the information which is intended for him or her. Login scenario’s can be programmed as an i-Task as well.

To see more complicated examples: goto the demo page.