T ask O riented P rogramming i n using Rinus Plasmeijer – Bas Lijnse - Peter Achten
description
Transcript of T ask O riented P rogramming i n using Rinus Plasmeijer – Bas Lijnse - Peter Achten
Task Oriented Programmingin
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
1
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
iTask Core
Basic tasksInteractive Tasks : EditorsNon-interactive Tasks: Lifting & ConversionIntegrated 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
+ iTask Library to support frequently occurring work patterns
+ Clean: general purpose pure functional programming language
Recursive -, higher order -, polymorphic -, overloaded -, generic - functionsHybrid typing: strongly statically typed + dynamic typing
Core Concepts
DataLocal data: Task ValuesShared data: Shared Data Sources
TasksBasic Tasks
Non-interactivereturn, throw, …
Interactive Editors
CombinatorsSequentialParallel
4
Core - Task Values
:: Task a typed 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 = ValRes TimeStamp (Value a)| e: ExcRes e & iTask e
:: Value a = NoVal | Val a Stability
:: Stability = Unstable | Stable
5
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 [ChoiceOption o] [o] Task o | descr d & iTask oupdateChoice :: d [ChoiceOption o] [o] o Task o | descr d & iTask o
enterMultipleChoice :: d [MultiChoiceOption o] [o] Task [o] | descr d & iTask oupdateMultipleChoice :: d [MultiChoiceOption o] [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
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 :== RWShared a Void:: WriteOnlyShared a :== RWShared Void a
8
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 FileexternalFile :: FilePath → Shared String // Ordinary
FilesqlShare :: SQLDatabase String … → ReadWriteShared r w // SQL Database
Reading an SDS:get :: (RWShared r w) → Task r | iTask r // read once
currentTime :: ReadOnlyShared TimecurrentDate :: ReadOnlyShared DatecurrentDateTime :: ReadOnlyShared DateTimecurrentUser :: ReadOnlyShared Userusers :: 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 w9
10
Interactive Editors on SDS’s
viewSharedInformation :: d [ViewOption r] (RWShared r w) Task r | descr d & iTask r
updateSharedInformation :: d [UpdateOption r w] (RWShared r 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
Editors on SDS’s
viewCurDateTime :: Task DateTimeviewCurDateTime
= viewSharedInformation "The current date and time is:" [] currentDateTime
Editors on SDS’s
twoTasks :: a → Task a | iTask a twoTasks v = withShared v doTasks
doTasks :: (Shared a) → Task a | iTask adoTasks sv = user1 @: updateSharedInformation sv
-|| user2 @: viewSharedInformation sv
12
Assign task to someonedo both tasks in parallel,
return first
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 &
iTask l & iTask r & iTask v
- One editor for handling all editor variants in the iTasks API
- An editable view v is created given the local value l and shared value r
- 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 Val l Unstable)
- Tasks do not terminate, but are discarded if they are not needed anymore
13
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" [] >>* [ OnAction ActionOk (ifValue isPalindrome (\v return
(Just v))) , OnAction ActionCancel (always (return
Nothing)) ]
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 a Task b
Task b
Task b
Core – Sequential Combinator
Combinator for Sequential Composition
(>>*) infixl 1 :: (Task a) [TaskStep a b] → Task b | iTask a & iTask b
:: TaskStep a b = OnAction Action (Value a → Maybe (Task b)) | OnValue (Value a → Maybe (Task b)) | E.e: OnException (e → Task b) & iTask e
:: Action = Action String [ActionOption]
:: ActionOption = ActionKey Hotkey | ActionWeight Int | ActionIcon String | ActionTrigger DoubleClick
:: Hotkey = { key :: Key, ctrl :: Bool, alt :: Bool, shift :: Bool }
ActionOk :== Action "Ok“ [ActionIcon "ok", ActionKey (unmodified KEY_ENTER)]
17
Core – Sequential Combinator
Combinator for Sequential Composition
(>>*) infixl 1 :: (Task a) [TaskStep a b] → Task b | iTask a & iTask b
:: TaskStep a b = OnAction Action (Value a → Maybe (Task b)) | OnValue (Value a → Maybe (Task b)) | E.e: OnException (e → Task b) & iTask e
:: Action = Action String [ActionOption]
:: ActionOption = ActionKey Hotkey | ActionWeight Int | ActionIcon String | ActionTrigger DoubleClick
:: Hotkey = { key :: Key, ctrl :: Bool, alt :: Bool, shift :: Bool }
ActionOpen :== Action "/File/Open" [ActionIcon "open", ActionKey (ctrl KEY_O)]
18
Core – Sequential Combinator
Combinator for Sequential Composition
(>>*) infixl 1 :: (Task a) [TaskStep a b] → Task b | iTask a & iTask b
:: TaskStep a b = OnAction Action (Value a → Maybe (Task b)) | OnValue (Value a → Maybe (Task b)) | E.e: OnException (e → Task b) & iTask e
always task = const (Just task)
ifValue pred task (Value v _) = if (pred v) (Just (task v)) NothingifValue _ _ _ = Nothing
hasValue task (Value v _) = Just (task v)hasValue _ _ = Nothing
ifStable task (Value v stable) = if stable (Just (task v)) NothingifStable _ _ = Nothing
19
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)) , OnAction ActionCancel (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)) , OnAction ActionCancel (always (return []))
]
22
Monadic-style
Monadic style:
(>>=) infix 1 :: (Task a) (a Task b) Task b | iTask a & iTask breturn :: a Task a | iTask a
(>>=) infix 1 :: (Task a) (a Task b) Task b | iTask a & iTask b(>>=) taska taskbf
= taska >>* [OnAction ActionContinue (hasValue taskbf)
, OnValue (ifStable taskbf)]
23
Simple Sum
calculateSum :: Task IntcalculateSum = 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
Every task produces a value of "type a"
A dedicated process table (TaskList) is created as SDSenabling the parallel tasks
to inspect each other
What kind of task is itand who should work
on it ?
Parallel - I
parallel :: d [(ParallelTaskType, (ReadOnlyShared (TaskList a)) Task a)] Task [(TaskTime, TaskValue a)] | descr d &
iTask a
Other tasks can seethe current values
of the parallel tasks
25
26
Parallel - I
parallel :: d [(ParallelTaskType, (ReadOnlyShared (TaskList a)) Task a)] Task [(TaskTime, TaskValue a)] | descr d & iTask a
:: ParallelTaskType = Embedded | Detached ManagementMeta
:: ManagementMeta = { title :: Maybe String, worker :: UserConstraint
, role :: Maybe Role , startAt :: Maybe DateTime
, completeBefore :: Maybe DateTime , notifyAt :: Maybe DateTime , priority :: TaskPriority }
:: UserConstraint = AnyUser| UserWithId UserId| UserWithRole Role
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 tasksor 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 banyTask :: [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 aallTasks tasks
= parallel Void [(Embedded, const t) \\ t tasks] @ reswhere res vs = [v \\ (_,Value v _) vs]
(-&&-) infixr 4 :: (Task a) (Task b) Task (a,b) | iTask a & iTask b(-&&-) taska taskb
= parallel Void [(Embedded, \_ taska @ Left),(Embedded, \_ taskb @ Right)] @? res
whereres (Value [(_, Value (Left a) _),(_,Value (Right b) _)] s) = Value (a,b) sres _ = 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 aanyTask tasks
= parallel Void [(Embedded, const t) \\ t tasks] @? reswhere
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= parallel Void [(Embedded, \_ taska @ Left),(Embedded, \_ taskb @ Right)] @?
Reswhere
res (Value [(_,Value (Left a) s),_] _) = Value a sres _ = 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 banyTask :: [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 Voidchat = get currentUser
>>= \me enterSharedChoice "Select someone to chat with:" [] users
>>= \you withShared ("","") (duoChat you me)
duoChat you me notes = chat you toView fromView notes
-||- (you @: chat me (toView o switch) (\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 (return Void)]
35
Example: Chat with someone
36
A Text Editor - I
editWithStatistics :: Task VoideditWithStatistics = enterInformation "Give name of text file you want to edit..." []
>>= \fileName let file = sharedStore fileName ""in parallel Void [ (Embedded, editFile fileName file)
, (Embedded, showStatistics file), (Embedded, replace initReplace file)]
>>* [ OnAction (Action "File/Quit") (always (return Void))]
37
A Text Editor - II
editFile :: String (Shared String) (SharedTaskList Void) Task VoideditFile fileName sharedFile _ = updateSharedInformation ("edit " +++ fileName) view sharedFile @ const Voidwhere
view = [UpdateWith toV fromV]toV text = Note textfromV _ (Note text) = text
38
A Text Editor - III
:: Statistics = {lineCount :: Int, wordCount :: Int}derive class iTask Statistics
showStatistics sharedFile _ = noStat <<@ Windowwhere noStat :: Task Void noStat = viewInformation Void [] Void >>* [ OnAction (Action "File/Show Statistics") (always showStat)
] showStat :: Task Void showStat = viewSharedInformation "Statistics:" [ViewWith stat] sharedFile >>* [ OnAction (Action "File/Hide Statistics") (always noStat)
]stat text = {lineCount = lengthLines text, wordCount = lengthWords text}where lengthLines "" = 0
lengthLines text = length (split "\n" text)
lengthWords "" = 0lengthWords text = length (split " " (replaceSubString "\n" " " text))
39
A Text Editor - IV
:: Replace = {search :: String, replaceBy :: String}derive class iTask Replace
replace cmnd sharedFile _ = noReplace cmndwhere noReplace :: Replace Task Void noReplace cmnd = viewInformation Void [] Void >>* [ OnAction (Action "File/Replace") (always (showReplace cmnd))
] showReplace :: Replace Task Void showReplace cmnd = updateInformation "Replace:" [] cmnd >>* [ OnAction (Action "Replace") (hasValue substitute) , OnAction (Action "Cancel") (always (noReplace cmnd)) ] substitute cmnd
= update (replaceSubString cmnd.search cmnd.replaceBy) sharedFile >>| showReplace cmnd
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
Semantics
The iTask system is quite powerful
tasks are defined on a complex domain and are reactivemulti-user systemshared data structures
The core is small
operational semantics described in Cleanreadable, concisetype checked by the compilerexecutable, one can check its behaviorblueprint for implementations
43
Core - Task Values
:: Task a typed unit of work which should deliver a value of type a
:: TaskResult a = ValRes TimeStamp (Value a)| e: ExcRes e & iTask e
:: Value a = NoVal | Val a Stability
:: Stability = Unstable | Stable
44
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
45
Semantics - Types
:: Event = RefreshEvent | EditEvent TaskNo Dynamic | ActionEvent TaskNo Action:: Response = EditorResponse EditorResponse | ActionResponse ActionResponse
:: EditorResponse = { description :: String , editValue :: (LocalVal, SharedVal) , editing :: EditMode }:: LocalVal :== Dynamic:: SharedVal :== Dynamic:: EditMode = Editing
| Displaying
:: ActionResponse :== [(Action, Bool)]:: Action = Action String
| ActionOk | ActionCancel | …
Semantics -Task Rewriting
evaluateTask :: (Task a) *World → *(Maybe a, *World) | iTask aevaluateTask 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 arewrite task st# (ev, nworld) = getNextEvent st.world# (t, nworld) = getCurrentTime nworld# ((Reduct result ntask, responses), st) = task ev {st & timeStamp = t, world = nworld}= case result of ValRes _ (Val a Stable) → (Just a, st) ExcRes _ → (Nothing, st) _ → rewrite ntask {st & world = informClients responses st.world}
47
Semantics -Task Rewriting
throw :: e → Task e | iTask ethrow e ev st = ((Reduct (ExcRes e) (throw e), []), st)
return :: a → Task areturn va ev st=:{timeStamp = t} = stable t va ev stwhere
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 conv ev st = case task ev st of
(Reduct (ValRes t aval) ntask, rsp, nst) → case conv aval of
Val b Stable → return b ev nst bval → ((Reduct (ValRes t bval) (ntask @? conv), rsp), nst)
(Reduct (ExcRes e) _,_,nst)→ throw e ev nst
48
iTask Core Summary - I
Basic Tasks / Editor
edit :: String l (RWShared r w) → (l r → 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
49
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 = OnAction Action ((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
50
51
Overview
Introduction to Task Oriented Programming
iTask Library
Task Values
Editors
Shared Data
Sequential Tasks
Parallel Tasks
Semantics
Conclusions and Future Work
Conclusions
Task Oriented Programming New style of programming for implementing multi-user web applications Focusing on tasks, not on the underlying technology All source code in one language Client receives JSON data, dedicated interpretation for PC, Tablet, Smart Phone
Core reactive tasks working on local and shared data shared data sources abstracting from any type of shared data editor: can handle all interactions sequential and parallel combinators
Operational Semantics defined in Clean readable, concise, type-checked, executable blueprint for implementations
52
53
Future Work
Real real-world applications Coast Guard (Bas Lijnse, PostDoc) TNO (Jurriën Stutterheim, PhD; Wessel van Staal, Master thesis) Dutch Navy (to be defined) Clean IDE ….
Applicability efficiency, scalability, security, version management, collaboration existing
systems…
Parallel & Distributed servers (Laszlo Domoszlai, PhD, Budapest)
Graphical Definition of iTasks, …
Semantics Reasoning ? Proving ? Testing ?
Server
Dynamic CodeClean Compiler
Clean Code
Dynamic LinkerError
Messages
54
Future Work
More real-world applications (with Dutch Navy, Coast Guard, TNO)
Applicability: efficiency, scalability, security, …
Reasoning ? Proving ? Testing ?
At run-time one can decide to evaluate a task on the client Intermediate SAPL code is just-in-time compiled to JavaScript HTML-5 features can be used
Graphical Definition of iTasks
Parallel executing servers
Server
iTask Web Service
iTask Combinator
LibraryiTask GIN
Dynamic CodeClean Compiler
Clean Code
Dynamic LinkerError
Messages
Questions ?
55