Difference between revisions of "Workflow examples"

From Clean
Jump to navigationJump to search
(Added a first example of dynamic workflow)
 
Line 8: Line 8:
 
* A user is given the task of producing some data (e.g. fill in a large form). Since he does not have all information to complete the task he decides to: fill in part of the form himself, divide the rest of the form and assigns the pieces to a number of experts. Depending on whether the user trusts his experts enough he may setup the task such that: A. the information of the expert is automatically merged with his own and the task is closed and data delivered, or B. he first wants to validate the information from the experts before passing the data along.
 
* A user is given the task of producing some data (e.g. fill in a large form). Since he does not have all information to complete the task he decides to: fill in part of the form himself, divide the rest of the form and assigns the pieces to a number of experts. Depending on whether the user trusts his experts enough he may setup the task such that: A. the information of the expert is automatically merged with his own and the task is closed and data delivered, or B. he first wants to validate the information from the experts before passing the data along.
  
 +
== '''Store for anything''' workflow ==
 +
* In this example we construct a '''store for anything''', i.e. the items that you want to sell are determined by their type. The store specification itself is fully overloaded and generic. Stock and orders are stored in a database. The complete source code can be downloaded at http://www.st.cs.ru.nl/papers/2009/shop.zip.
 +
* We define two workflow situations in this case study.
 +
* A '''catalogue management workflow''' in which a worker can edit, remove, and add items in the store. This is an example of a regular workflow, because each item in stock can be manipulated in the same way. This can be expressed concisely by a '''map''' of the stock items.
 +
 +
manageCatalog          :: a [HtmlTag] -> Task a | iData, DB a
 +
manageCatalog _ prompt = stopTask (prompt ?>> foreverTask (dbReadAll =>> browseCatalog))
 +
where
 +
  browseCatalog        :: [a] -> Task a | iData, DB a
 +
  browseCatalog items  = orTasksVert (map itemActions items ++ [chooseTask_btn [] [("Append",new)]])
 +
  where
 +
      new              = dbCreateItem =>> \first -> editTask "Store" first =>> dbUpdateItem
 +
 +
      itemActions      :: a -> Task a | iData, DB a
 +
      itemActions item  = chooseTask_btn [toHtml item]
 +
                            [("Edit",  editTask "Store" item =>> dbUpdateItem)
 +
                            ,("Delete", dbDeleteItem (getItemId item) #>> return item)
 +
                            ]
 +
 +
* A '''customer workflow'''. A customer can browse the shop catalogue, add and remove items in a shopping cart, buy the selected items of the cart, or leave the shop. This is an example of an irregular recursive workflow.
 +
 +
doShopping                :: (Cart a) [a] -> Task (ShopAction,Cart a) | iData, Product a
 +
doShopping cart []        = (shopPrompt ++ [normalText "Currently no items in catalogue, sorry."])
 +
                              ?>> OK #>> return (LeaveShop,cart)
 +
doShopping cart items      = orTasksVert [ navigateShop shopPrompt cart : map (itemActions cart) items ]
 +
where
 +
    itemActions            :: (Cart a) a -> Task (ShopAction,Cart a) | iData, Product a
 +
    itemActions cart item  = chooseTask_btn [toHtml item] [("Add to Cart", return (ToCart, add (toCartItem item) cart))]
 +
    where
 +
      add                  :: (CartItem a) [CartItem a] -> [CartItem a]
 +
      add new []          = [new]
 +
      add new [item:items] = if (eqItemNr new item)
 +
                                [amountOrderedUpd item (amountOrderedOf item+1):items]
 +
                                [item:add new items]
 +
 +
* '''Shop navigation''' is a matter of selecting the right button:
 +
 +
navigateShop              :: [HtmlTag] (Cart a) -> Task (ShopAction, Cart a) | iData a
 +
navigateShop prompt cart  = chooseTask []
 +
                                [ ("Do Shopping",      return (ToShop,  cart))
 +
                                , ("Check Out And Pay", return (ToPay,    cart))
 +
                                , ("Show Cart",        return (ToCart,  cart))
 +
                                , ("Leave Shop",        return (LeaveShop,cart))
 +
                                ] <<? [ BrTag  [], boldText "Total cost of ordered items = ", toHtml (totalCost cart)
 +
                                      , DivTag [] prompt ]
 +
 +
* The irregular recursive structure is connected together with the following two, mutually recursive, functions:
 +
browseShop                :: (Cart a) [HtmlTag] [HtmlTag] -> Task Void | iData, DB, Product a
 +
browseShop initCart shopPrompt cartPrompt
 +
                            = dbReadAll      =>> \items ->
 +
                              doShopping initCart items =>>
 +
                              doAction  initCart items
 +
 +
doAction                  :: (Cart a) [a] (ShopAction, Cart a) -> Task Void | iData, DB, Product a
 +
doAction initCart items (action,cart)
 +
                            = case action of
 +
                                LeaveShop = return Void
 +
                                ToCart    = showCart  cart      =>> doAction initCart items
 +
                                ToShop    = doShopping cart items =>> doAction initCart items
 +
                                ToPay    = checkOutAndPay cart  #>> browseShop initCart shopPrompt cartPrompt
 +
 +
* Do you want to sell books? Let's make a book type:
 +
:: Book                    = { id_    :: DBRef Book
 +
                              , title  :: String
 +
                              , author  :: String
 +
                              , price  :: HtmlCurrency
 +
                              , inStock :: Int
 +
                              }
 +
 +
* It has to connect to a database:
 +
instance DB Book where databaseId        = mkDBid "books" LSTxtFile
 +
                        getItemId item    = id_Of  item
 +
                        setItemId id item  = id_Upd item id
 +
 +
* It has to connect to the store, that wants to know what kind of product it is:
 +
class Product a | nameOf, priceOf, id_Of, inStockOf a
 +
 +
instance nameOf    Book where nameOf    r = r.Book.title
 +
instance priceOf  Book where priceOf  r = r.Book.price
 +
instance id_Of    Book where id_Of    r = r.Book.id_
 +
instance inStockOf Book where inStockOf r = r.Book.inStock
 +
 +
* It has to be the default product and cart content:
 +
defaultProduct            :: Book
 +
defaultProduct            = createDefault
 +
 +
defaultCart                :: Cart Book
 +
defaultCart                = createDefault
 +
 +
* You're done!
  
 
[[Category:iTasks]]
 
[[Category:iTasks]]

Revision as of 17:35, 14 March 2009

To determine the direction of the iTasks research we need examples of workflow scenarios to see if they can be implemented in the system.

Basic workflow

Lazy workflow

Dynamic workflow

  • A user is given the task of producing some data (e.g. fill in a large form). Since he does not have all information to complete the task he decides to: fill in part of the form himself, divide the rest of the form and assigns the pieces to a number of experts. Depending on whether the user trusts his experts enough he may setup the task such that: A. the information of the expert is automatically merged with his own and the task is closed and data delivered, or B. he first wants to validate the information from the experts before passing the data along.

Store for anything workflow

  • In this example we construct a store for anything, i.e. the items that you want to sell are determined by their type. The store specification itself is fully overloaded and generic. Stock and orders are stored in a database. The complete source code can be downloaded at http://www.st.cs.ru.nl/papers/2009/shop.zip.
  • We define two workflow situations in this case study.
  • A catalogue management workflow in which a worker can edit, remove, and add items in the store. This is an example of a regular workflow, because each item in stock can be manipulated in the same way. This can be expressed concisely by a map of the stock items.
manageCatalog          :: a [HtmlTag] -> Task a | iData, DB a
manageCatalog _ prompt = stopTask (prompt ?>> foreverTask (dbReadAll =>> browseCatalog))
where
  browseCatalog        :: [a] -> Task a | iData, DB a
  browseCatalog items  = orTasksVert (map itemActions items ++ [chooseTask_btn [] [("Append",new)]])
  where
     new               = dbCreateItem =>> \first -> editTask "Store" first =>> dbUpdateItem

     itemActions       :: a -> Task a | iData, DB a
     itemActions item  = chooseTask_btn [toHtml item] 
                           [("Edit",   editTask "Store" item =>> dbUpdateItem)
                           ,("Delete", dbDeleteItem (getItemId item) #>> return item)
                           ]
  • A customer workflow. A customer can browse the shop catalogue, add and remove items in a shopping cart, buy the selected items of the cart, or leave the shop. This is an example of an irregular recursive workflow.
doShopping                 :: (Cart a) [a] -> Task (ShopAction,Cart a) | iData, Product a
doShopping cart []         = (shopPrompt ++ [normalText "Currently no items in catalogue, sorry."])
                             ?>> OK #>> return (LeaveShop,cart)
doShopping cart items      = orTasksVert [ navigateShop shopPrompt cart : map (itemActions cart) items ] 
where
   itemActions             :: (Cart a) a -> Task (ShopAction,Cart a) | iData, Product a
   itemActions cart item   = chooseTask_btn [toHtml item] [("Add to Cart", return (ToCart, add (toCartItem item) cart))]
   where
      add                  :: (CartItem a) [CartItem a] -> [CartItem a]
      add new []           = [new]
      add new [item:items] = if (eqItemNr new item) 
                                [amountOrderedUpd item (amountOrderedOf item+1):items]
                                [item:add new items]
  • Shop navigation is a matter of selecting the right button:
navigateShop               :: [HtmlTag] (Cart a) -> Task (ShopAction, Cart a) | iData a
navigateShop prompt cart   = chooseTask [] 
                                [ ("Do Shopping",       return (ToShop,   cart))
                                , ("Check Out And Pay", return (ToPay,    cart))
                                , ("Show Cart",         return (ToCart,   cart))
                                , ("Leave Shop",        return (LeaveShop,cart))
                                ] <<? [ BrTag  [], boldText "Total cost of ordered items = ", toHtml (totalCost cart)
                                      , DivTag [] prompt ]
  • The irregular recursive structure is connected together with the following two, mutually recursive, functions:
browseShop                 :: (Cart a) [HtmlTag] [HtmlTag] -> Task Void | iData, DB, Product a
browseShop initCart shopPrompt cartPrompt
                           = dbReadAll      =>> \items ->
                             doShopping initCart items =>> 
                             doAction   initCart items
doAction                   :: (Cart a) [a] (ShopAction, Cart a) -> Task Void | iData, DB, Product a
doAction initCart items (action,cart)
                           = case action of
                               LeaveShop = return Void
                               ToCart    = showCart   cart       =>> doAction initCart items
                               ToShop    = doShopping cart items =>> doAction initCart items
                               ToPay     = checkOutAndPay cart   #>> browseShop initCart shopPrompt cartPrompt
  • Do you want to sell books? Let's make a book type:
:: Book                    = { id_     :: DBRef Book
                             , title   :: String
                             , author  :: String
                             , price   :: HtmlCurrency
                             , inStock :: Int
                             }
  • It has to connect to a database:
instance DB Book where databaseId         = mkDBid "books" LSTxtFile
                       getItemId item     = id_Of  item
                       setItemId id item  = id_Upd item id
  • It has to connect to the store, that wants to know what kind of product it is:
class Product a | nameOf, priceOf, id_Of, inStockOf a
instance nameOf    Book where nameOf    r = r.Book.title
instance priceOf   Book where priceOf   r = r.Book.price
instance id_Of     Book where id_Of     r = r.Book.id_
instance inStockOf Book where inStockOf r = r.Book.inStock
  • It has to be the default product and cart content:
defaultProduct             :: Book
defaultProduct             = createDefault
defaultCart                :: Cart Book
defaultCart                = createDefault
  • You're done!