1 / 55

T ask O riented P rogramming i n using Rinus Plasmeijer – Bas Lijnse - Peter Achten

T ask O riented P rogramming i n using Rinus Plasmeijer – Bas Lijnse - Peter Achten Pieter Koopman - Steffen Michels – Jurriën Stutterheim Jan Martin Jansen (NLDA) - Laszlo Domoszlai (ELTE) Part 2/2 Radboud University Nijmegen. Overview.

vilina
Download Presentation

T ask O riented P rogramming i n using Rinus Plasmeijer – Bas Lijnse - Peter Achten

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Task Oriented Programming in using Rinus Plasmeijer–Bas Lijnse- Peter Achten Pieter Koopman- Steffen Michels–JurriënStutterheim Jan Martin Jansen (NLDA) - Laszlo Domoszlai (ELTE) Part 2/2 Radboud University Nijmegen

  2. Overview • Introduction to Task Oriented Programming • iTask Library • Task Values • Editors • Shared Data • Sequential Tasks • Parallel Tasks • Semantics • Conclusions and Future Work

  3. Embedded Domain Specific Language iTaskCore Basic tasks Interactive Tasks : Editors Non-interactive Tasks: Lifting & Conversion Integrated Tasks: web-service-call, OS-call, exec application, access a database Combinators for combining tasks Define control flow (sequential / parallel) and data flow between tasks + iTaskLibrary to support frequently occurring work patterns + Clean: general purpose pure functional programming language Recursive -, higher order -, polymorphic -, overloaded -, generic - functions Hybrid typing: strongly statically typed + dynamic typing

  4. Core Concepts • Data • Local data: Task Values • Shared data: Shared Data Sources • Tasks • Basic Tasks • Non-interactive • return, throw, … • Interactive • Editors • Combinators • Sequential • Parallel

  5. Core - Task Values :: Task atyped unit of work which should deliver a value of type a While the task is going on, its value may change over time :: TaskResult a = ValResTimeStamp (Value a) | e: ExcRese & iTask e :: Value a = NoVal | Vala Stability :: Stability = Unstable | Stable NoVal Val a Unstable Vala Stable

  6. Interactive Editors (see InteractionTasks.dcl) Basic tasks: Interactive editor for filling in forms of a certain type: viewInformation :: d [ViewOption a] a  Task a | descr d & iTask a enterInformation :: d [EnterOption a]  Task a | descr d & iTask a updateInformation:: d [UpdateOption a a] a  Task a | descr d & iTask a enterChoice :: d [ChoiceOptiono] [o]  Task o | descr d & iTask o updateChoice :: d [ChoiceOptiono] [o] o Task o | descr d & iTask o enterMultipleChoice :: d [MultiChoiceOptiono] [o] Task [o] | descr d & iTask o updateMultipleChoice :: d [MultiChoiceOptiono] [o] [o] Task [o] | descr d & iTask o

  7. Overview • Introduction to Task Oriented Programming • iTask Library • Task Values • Editors • Shared Data • Sequential Tasks • Parallel Tasks • Semantics • Conclusions and Future Work

  8. Core - Shared Data Sources SDS: one abstraction layer for any type of shared data: easy to use for the progammer - Shared Memory , Files , Cloud , Time , Sensors , …. - Reading and Writing can be of different type - SDS’s can be composed from others (e.g. lenses a la Benjamin Pierce) :: RWShared r w :: Shared a :== RWShared a a ::ReadOnlyShared a :==RWShareda Void ::WriteOnlyShared a :==RWSharedVoid a

  9. Shared Data Sources Creating an SDS: withShared :: a ((Shared a) →Task b) →Task b | iTask b // Shared memory sharedStore:: String a→ Shared a | iTask a // Special File externalFile :: FilePath→Shared String // Ordinary File sqlShare :: SQLDatabase String … →ReadWriteShared r w// SQL Database Reading an SDS: get :: (RWShared r w) →Task r | iTask r // read once currentTime::ReadOnlyShared Time currentDate::ReadOnlySharedDate currentDateTime::ReadOnlySharedDateTime currentUser::ReadOnlyShared User users :: ReadOnlyShared [User] Updating an SDS: set :: w (RWShared r w) →Task w | iTask w // write once update ::(r → w) (RWShared r w)→ Task w | iTask r & iTask w

  10. Interactive Editors on SDS’s viewSharedInformation:: d [ViewOption r] (RWSharedr w) Task r | descr d & iTask r updateSharedInformation :: d [UpdateOption r w] (RWSharedr w) Task w | descr d & iTask r & iTask w enterSharedChoice :: d [ChoiceOption o] (RWShared[o] w) Task o | descr d & iTask o & iTask w updateSharedChoice :: d [ChoiceOption o] (RWShared[o] w) o Task o | descr d & iTask o & iTask w enterSharedMultipleChoice :: d [MultiChoiceOption o] (RWShared[o] w) Task [o] | descr d & iTask o & iTask w updateSharedMultipleChoice :: d [MultiChoiceOption o] (RWShared[o] w) [o] Task [o] | descr d & iTask o & iTask w

  11. Editors on SDS’s viewCurDateTime:: Task DateTime viewCurDateTime = viewSharedInformation"The current date and time is:" [] currentDateTime

  12. Editors on SDS’s twoTasks:: a → Task a | iTask a twoTasksv = withShared v doTasks doTasks:: (Shared a)→ Task a | iTask a doTaskssv = user1 @:updateSharedInformationsv -|| user2 @: viewSharedInformationsv Assign task to someone do both tasks in parallel, return first

  13. Core - Basic Tasks : One editor for all cases • Basic Tasks / Editor edit :: d l (ROShared r) (r→ (l,v)) (l r v→(l,v))→Task l | descr d & iTaskl & iTask r & iTask v • One editor for handling all editor variants in the iTasks API • An editable viewv is created given the local valuel and shared valuer • The view v is updated when v is edited or someone changes r • An editor task never delivers a stable value (it is either NoVal or VallUnstable) • Tasks do not terminate, but are discarded if they are not needed anymore

  14. Overview • Introduction to Task Oriented Programming • iTask Library • Task Values • Editors • Shared Data • Sequential Tasks • Parallel Tasks • Semantics • Conclusions and Future Work

  15. Sequential Combinator: >>* palindrome :: Task (Maybe String) palindrome = enterInformation "Enter a palindrome" [] >>* [ OnActionActionOk (ifValueisPalindrome (\v  return (Just v))) , OnActionActionCancel (always (returnNothing)) ]

  16. Sequential Combinator: >>* >>* • Observe Task a, continue with one of the Task b's: - if a certain action is performed by the end-user - if the value of the observed task is satisfying a certain predicate - or the observed task has raised an exception to be handled here Task b Task b Task b Task a

  17. Core – Sequential Combinator • Combinator for Sequential Composition (>>*) infixl 1 :: (Task a) [TaskStep a b] →Task b | iTask a & iTask b :: TaskStep a b = OnActionAction(Value a→Maybe(Task b)) | OnValue(Value a→Maybe (Task b)) | E.e: OnException (e→Task b) & iTask e :: Action = ActionString[ActionOption] :: ActionOption = ActionKey Hotkey | ActionWeightInt | ActionIcon String |ActionTriggerDoubleClick :: Hotkey = { key :: Key, ctrl :: Bool, alt :: Bool, shift :: Bool} ActionOk :== Action "Ok“ [ActionIcon"ok", ActionKey(unmodified KEY_ENTER)]

  18. Core – Sequential Combinator • Combinator for Sequential Composition (>>*) infixl 1 :: (Task a) [TaskStep a b] →Task b | iTask a & iTask b :: TaskStep a b = OnActionAction(Value a→Maybe(Task b)) | OnValue(Value a→Maybe (Task b)) | E.e: OnException (e→Task b) & iTask e :: Action = ActionString [ActionOption] :: ActionOption = ActionKeyHotkey | ActionWeightInt | ActionIconString |ActionTriggerDoubleClick :: Hotkey = { key :: Key, ctrl :: Bool, alt :: Bool, shift :: Bool} ActionOpen:== Action "/File/Open" [ActionIcon"open", ActionKey(ctrlKEY_O)]

  19. Core – Sequential Combinator • Combinator for Sequential Composition (>>*) infixl 1 :: (Task a) [TaskStep a b] →Task b | iTask a & iTask b :: TaskStep a b = OnActionAction(Value a→Maybe(Task b)) | OnValue(Value a→Maybe (Task b)) | E.e: OnException (e→Task b) & iTask e alwaystask = const(Justtask) ifValuepredtask (Value v _) = if (pred v) (Just (task v)) Nothing ifValue_ _ _ = Nothing hasValuetask (Value v _) = Just (task v) hasValue_ _ = Nothing ifStabletask(Valuev stable) = ifstable (Just (task v)) Nothing ifStable_ _ = Nothing

  20. Recursive Tasks person1by1 :: [Person] Task [Person] person1by1 persons = enterInformation "Add a person" [] >>* [ OnAction (Action "Add" []) (hasValue(\vperson1by1 [v : persons]) , OnAction (Action "Finish" []) (always (return persons)) , OnActionActionCancel (always (return[])) ]

  21. Recursive Tasks person1by1 :: [Person] Task [Person] person1by1 persons = enterInformation "Add a person" [] -|| viewInformation "List so far.." [] persons >>* [ OnAction (Action "Add" []) (hasValue(\vperson1by1 [v : persons]) , OnAction (Action "Finish" []) (always (return persons)) , OnActionActionCancel (always (return[])) ]

  22. Monadic-style Monadic style: (>>=) infix 1 :: (Task a) (a  Task b)  Task b | iTask a & iTask b return :: a  Task a | iTask a (>>=) infix 1 :: (Task a) (a  Task b)  Task b | iTask a & iTask b (>>=) taska taskbf = taska >>* [OnActionActionContinue (hasValue taskbf) , OnValue (ifStable taskbf) ]

  23. Simple Sum calculateSum :: Task Int calculateSum = enterInformation ("Number 1","Enter a number") [] >>= \num1 enterInformation ("Number 2","Enter another number") [] >>= \num2  viewInformation ("Sum","The sum of those numbers is:") [] (num1 + num2)

  24. Overview • Introduction to Task Oriented Programming • iTask Library • Task Values • Editors • Shared Data • Sequential Tasks • Parallel Tasks • Semantics • Conclusions and Future Work

  25. Parallel - I parallel :: d [(ParallelTaskType, (ReadOnlyShared (TaskList a))  Task a)] Task [(TaskTime, TaskValue a)] | descr d & iTask a What kind of task is it and who should work on it ? A dedicated process table (TaskList) is created as SDS enabling the parallel tasks to inspect each other Other tasks can see the current values of the parallel tasks Every task produces a value of "type a"

  26. Parallel - I parallel :: d [(ParallelTaskType, (ReadOnlyShared (TaskList a))  Task a)] Task [(TaskTime, TaskValue a)] | descr d & iTask a :: ParallelTaskType = Embedded | DetachedManagementMeta :: ManagementMeta = { title :: Maybe String , worker :: UserConstraint , role :: Maybe Role , startAt :: Maybe DateTime , completeBefore :: Maybe DateTime , notifyAt :: Maybe DateTime , priority :: TaskPriority } :: UserConstraint = AnyUser | UserWithIdUserId | UserWithRoleRole

  27. Parallel - II parallel :: d [(ParallelTaskType, (ReadOnlyShared (TaskList a))  Task a)] Task [(TaskTime, TaskValue a)] | descr d & iTask a :: TaskList a = { listId :: TaskListId a , items :: [TaskListItem a] } :: TaskListItem a = { taskId :: TaskId , value :: TaskValue a , taskMeta :: TaskMeta , managementMeta :: Maybe ManagementMeta , progressMeta :: Maybe ProgressMeta }

  28. Parallel Task Handling parallel :: d [(ParallelTaskType, (ReadOnlyShared (TaskList a))  Task a)] Task [(TaskTime, TaskValue a)] | descr d & iTask a appendTask :: ParallelTaskType ((ReadOnlyShared (TaskList a))  Task a) (ReadOnlyShared (TaskList a)) Task TaskId | iTask a removeTask :: TaskId(ReadOnlyShared (TaskList a)) Task Void | iTask a Only the parallel tasks have access to their process table and they can add new tasks or kill existing ones

  29. Handy predefined functions based on parallel and : return values of all (embedded) parallel tasks: allTasks :: [Task a] Task [a] | iTask a (-&&-) infixr 4 :: (Task a) (Task b) Task (a, b) | iTask a & iTask b or: return result of (embedded) parallel tasks yielding a value as first: eitherTask :: (Task a) (Task b) Task (Either a b) | iTask a & iTask b anyTask :: [Task a] Task a | iTask a (-||-) infixr 3 :: (Task a) (Task a) Task a | iTask a one-of: start two tasks, but we are only interested in the result of one of them, use the other to inform: (-||) infixl 3 :: (Task a) (Task b) Task a | iTask a & iTask b (||-) infixr 3 :: (Task a) (Task b) Task b | iTask a & iTask b

  30. Handy predefined functions based on parallel allTasks :: [Task a] Task [a] | iTask a allTasks tasks = parallelVoid [(Embedded, const t) \\ t  tasks] @res whereres vs = [v \\ (_,Value v _)  vs] (-&&-) infixr 4 :: (Task a) (Task b) Task (a,b) | iTask a & iTask b (-&&-) taska taskb = parallelVoid [(Embedded, \_  taska @Left),(Embedded, \_  taskb @Right)] @? res where res (Value [(_, Value (Left a) _),(_,Value (Right b) _)] s) = Value (a,b) s res _ = NoValue The following conversion functions have already been introduced : • (@?) infixl 1 :: (Task a) (Value a→Value b) →Task b | iTask a & iTask b • (@) infixl 1 :: (Task a) (a→b) →Task b | iTask a & iTask b

  31. Handy predefined functions based on parallel anyTask :: [Task a] Task a | iTask a anyTask tasks = parallelVoid [(Embedded, const t) \\ t  tasks] @? res where res (Value l _) = hd ([v \\ (_,v=:(Value _ Stable))  l] ++ [v \\ (_,v=:(Value _ _)) sortBy (\a b -> fst a > fst b) l] ++ [NoValue]) res _ = NoValue (-||) infixl 3 :: (Task a) (Task b) Task a | iTask a & iTask b (-||) taska taskb = parallelVoid [(Embedded, \_  taska @Left),(Embedded, \_  taskb @Right)] @? Res where res (Value [(_,Value (Left a) s),_] _) = Value a s res _ = NoValue

  32. Handy predefined functions based on parallel and : return values of all (embedded) parallel tasks: allTasks :: [Task a] Task [a] | iTask a (-&&-) infixr 4 :: (Task a) (Task b) Task (a, b) | iTask a & iTask b or: return result of (embedded) parallel tasks yielding a value as first: eitherTask :: (Task a) (Task b) Task (Either a b) | iTask a & iTask b anyTask :: [Task a] Task a | iTask a (-||-) infixr 3 :: (Task a) (Task a) Task a | iTask a one-of: start two tasks, but we are only interested in the result of one of them, use the other to inform: (||-) infixr 3 :: (Task a) (Task b) Task b | iTask a & iTask b (-||) infixl 3 :: (Task a) (Task b) Task a | iTask a & iTask b assign a task to a specific user: (@:) infix 3 :: User (Task a) Task a | iTask a

  33. Standard iTask Client

  34. Example: Chat with someone chat :: Task Void chat = getcurrentUser >>= \me enterSharedChoice "Select someone to chat with:" [] users >>= \youwithShared ("","") (duoChatyou me) duoChat you me notes = chat you toViewfromView notes -||- (you @:chat me (toViewoswitch) (\a v switch (fromView a v)) notes) where toView (you, me) = (Display you, Note me) fromView _ (Display you, Note me) = (you, me) switch (you, me) = (me, you) chat who toV fromV notes = updateSharedInformation ("Chat with " <+++ who) [UpdateWith toV fromV] notes >>* [OnAction (Action "Stop") always (returnVoid)]

  35. Example: Chat with someone

  36. A Text Editor - I • editWithStatistics :: Task Void • editWithStatistics • = enterInformation "Give name of text file you want to edit..." [] • >>= \fileNamelet file = sharedStorefileName "" • in parallelVoid [ (Embedded, editFilefileName file) • , (Embedded, showStatistics file) • , (Embedded, replaceinitReplace file) • ] • >>* [ OnAction (Action "File/Quit") (always(returnVoid))]

  37. A Text Editor - II editFile :: String (Shared String) (SharedTaskList Void) Task Void editFilefileNamesharedFile _ = updateSharedInformation ("edit " +++ fileName) viewsharedFile@ constVoid where view = [UpdateWithtoVfromV] toV text = Note text fromV _ (Note text) = text

  38. A Text Editor - III :: Statistics = {lineCount:: Int, wordCount:: Int} deriveclassiTaskStatistics showStatisticssharedFile _ = noStat<<@ Window where noStat :: Task Void noStat = viewInformationVoid [] Void >>* [ OnAction (Action "File/Show Statistics") (alwaysshowStat) ] showStat :: Task Void showStat = viewSharedInformation "Statistics:" [ViewWithstat] sharedFile >>* [ OnAction (Action "File/Hide Statistics") (alwaysnoStat) ] stat text = {lineCount= lengthLines text, wordCount= lengthWords text} wherelengthLines "" = 0 lengthLines text = length (split "\n" text) lengthWords "" = 0 lengthWords text = length (split " " (replaceSubString "\n" " " text))

  39. A Text Editor - IV :: Replace = {search :: String, replaceBy :: String} deriveclassiTaskReplace replacecmndsharedFile _ = noReplacecmnd where noReplace :: ReplaceTask Void noReplacecmnd = viewInformationVoid [] Void >>* [ OnAction (Action "File/Replace") (always(showReplacecmnd)) ] showReplace :: ReplaceTask Void showReplacecmnd = updateInformation "Replace:" [] cmnd >>* [ OnAction (Action "Replace") (hasValuesubstitute) , OnAction (Action "Cancel") (always(noReplacecmnd)) ] substitutecmnd = update (replaceSubStringcmnd.searchcmnd.replaceBy) sharedFile >>| showReplacecmnd

  40. Incidone – Coast Guard Search and Rescue Support

  41. iTask Client

  42. Overview • Introduction to Task Oriented Programming • iTask Library • Task Values • Editors • Shared Data • Sequential Tasks • Parallel Tasks • Semantics • Conclusions and Future Work

  43. Semantics The iTask system is quite powerful • tasks are defined on a complex domain and are reactive • multi-user system • shared data structures The core is small • operational semantics described in Clean • readable, concise • type checked by the compiler • executable, one can check its behavior • blueprint for implementations

  44. Core - Task Values • :: Task atyped unit of work which should deliver a value of type a :: TaskResult a = ValResTimeStamp(Value a) | e: ExcRese & iTask e :: Value a = NoVal | Vala Stability :: Stability = Unstable | Stable NoVal Val a Unstable Vala Stable

  45. Semantics - What is a Task ? :: Task a :== Event*State→*((Reduct a, [(TaskNo, Response)]), *State) :: Reduct a = Reduct (TaskResult a) (Task a) :: *State = { taskNo :: TaskNo // highest unassigned number , timeStamp :: TimeStamp // current time stamp , mem :: [SharedValue] // memory shared between tasks , world :: *World // enables I/O in a pure FPL } :: SharedValue :== Dynamic Current Value Remaining Task To do

  46. Semantics - Types :: Event = RefreshEvent | EditEventTaskNo Dynamic | ActionEventTaskNo Action :: Response = EditorResponseEditorResponse | ActionResponseActionResponse :: EditorResponse = { description :: String , editValue :: (LocalVal,SharedVal) , editing :: EditMode } :: LocalVal :== Dynamic :: SharedVal :== Dynamic :: EditMode = Editing | Displaying :: ActionResponse :== [(Action,Bool)] :: Action = ActionString | ActionOk | ActionCancel | …

  47. Semantics -Task Rewriting evaluateTask :: (Task a) *World→ *(Maybe a,*World) | iTask a evaluateTask task world # st = {taskNo = 0, timeStamp = 0, mem = [], world = world} # (ma, st) = rewrite task st = (ma, st.world ) rewrite :: (Task a)*State→ *(Maybe a,*State) | iTask a rewrite task st # (ev, nworld) = getNextEventst.world # (t, nworld) = getCurrentTimenworld # ((Reductresultntask, responses), st) = task ev {st & timeStamp = t, world = nworld} = caseresultof ValRes _ (Val a Stable) → (Just a, st) ExcRes _ → (Nothing, st) _ →rewritentask {st & world = informClients responses st.world}

  48. Semantics -Task Rewriting throw :: e→Task e | iTask e throw e evst = ((Reduct (ExcRes e) (throw e), []), st) return :: a→Task a returnvaevst=:{timeStamp = t} = stable t vaevst where stable t va _ st= (Reduct (ValRes t (Val va Stable)) (stable t va),[],st) (@?) infixl 1 :: (Task a) ((Value a)→Value b) →Task b | iTask a & iTask b (@?) task convevst = case task evstof (Reduct (ValRes t aval) ntask, rsp, nst) →caseconvavalof Val b Stable→return b evnst bval→ ((Reduct (ValRes t bval) (ntask@?conv), rsp), nst) (Reduct (ExcRes e) _,_,nst) →throw e evnst

  49. iTask Core Summary - I • Basic Tasks / Editor edit :: Stringl (RWShared r w) → (lr→Maybe a) →Task a | iTask l & iTask r • Basic Tasks / Return return:: a→Task a | iTask a • Basic Tasks / Exception Handling throw :: e→Task e | iTask e • Shared Data Sources withShared :: a ((Shared a) →Task b) →Task b | iTask a

  50. iTask Core Summary - II • Combinator for Conversion of Task Values (@?) infixl 1 :: (Task a) ((Value a) →Value b) →Task b | iTask a & iTask b • Combinator for Sequential Composition (>>*) infixl 1 :: (Task a) [TaskStep a b]→Task b | iTask a & iTask b :: TaskStep a b = OnActionAction ((Value a) →Bool) ((Value a) →Task b) | OnValue ((Value a) →Bool) ((Value a) →Task b) | E.e: OnException (e→Task b) & iTask e • Combinator for Parallel Composition parallel :: [RWShared [(Int, Reduct a)] Void] →Task [(TimeStamp, Value a)] | iTask a

More Related