Difference between revisions of "Workflow examples"
From Clean
Jump to navigationJump to searchBas Lijnse (talk | contribs) (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!