Title: Generic Graphical User Interfaces for the WEB ___________
1GenericGraphical User Interfacesfor the
WEB___________
Rinus Plasmeijer - Peter Achten University of
Nijmegen www.cs.kun.nl/clean
2Snapshot from Clean's CD shop
3Overview of the talk
- Cleans generic Graphical Editor Components
- Architecture Web applications ltgt Architecture
normal Clean application - Generation of Html code
- Automatic Generation of Html code for any Clean
type - Automatic Generation of simple interactive forms
for any Clean type - Separating Data from Views allowing to make any
kind of form - Implementation
- Arrows
- Conclusion Future Research
4Overview of the talk
- Cleans generic Graphical Editor Components
- Architecture Web applications ltgt Architecture
normal Clean application - Generation of Html code
- Automatic Generation of Html code for any Clean
type - Automatic Generation of simple interactive forms
for any Clean type - Separating Data from Views allowing to make any
kind of form - Implementation
- Arrows
- Conclusion Future Research
5Graphical Editor Components in Clean
- Start World ? World
- Start world startFormCircuit myEditor 1,5,2
world - myEditor edit "List" gtgtgt arr toBalancedTree
gtgtgt display "Balanced Tree" -
-
6mutual dependent arrows
- myEditor feedback ( arr toPounds gtgtgt
- edit Pounds gtgtgt
- arr toEuros gtgtgt
- editEuros )
-
7Graphical Editor Components
- Given any type, an editor can be generated for it
automatically - Editors can be connected the output of one can
be used as input for another - Editors even may be mutual dependent
- One can make "circuits" of editors using special
combinators (arrows) - Even editors for higher order types can be
generated (editing of functions) - You can easily define your favourite "look" for
any type (buttons, menu's) - Great for rapid prototyping no low level IO
programming needed
8Overview of the talk
- Cleans generic Graphical Editor Components
- Architecture Web applications ltgt Architecture
normal Clean application - Generation of Html code
- Automatic Generation of Html code for any Clean
type - Automatic Generation of simple interactive forms
for any Clean type - Separating Data from Views allowing to make any
kind of form - Implementation
- Arrows
- Conclusion Future Research
9Architecture "normal" Clean Application
10Architecture Clean application for the Web
11Architecture Clean application for the Web
12How to achieve Graphical Editor Components for
the Web ?
- We need to be able to generate Html code
- For any Clean type, an Html Form has to be
generated automatically - Deal with interaction a change made in a Form
has to be handled automatically - We need to be able to connect Forms
- We have to be able to make sophisticated Forms
with any look we like - Clean application is a pure function it "just"
need its previous state
13Overview of the talk
- Cleans generic Graphical Editor Components
- Architecture Web applications ltgt Architecture
normal Clean application - Generation of Html code
- Automatic Generation of Html code for any Clean
type - Automatic Generation of simple interactive forms
for any Clean type - Separating Data from Views allowing to make any
kind of form - Implementation
- Arrows
- Conclusion Future Research
14Generating Html Code
- An Algebraic Data Type has been defined
isomorphic with Html, Style sheets - Html Html Head Rest
- Head Head HeadAttr HeadTag
- Rest Body BodyAttr BodyTag
- BodyTag A A_Attr BodyTag
-
- Var Std_Attr String
- Stable Table_Attr BodyTag
- BodyTag BodyTag
EmptyBody - any value of Html ADT can be converted to real
Html-code, using a generic function - generic gHpr a File a ? File
15Playing with the world of web pages
- An interactive Clean program has type
- Start World ? World
- An interactive Clean Web program has type
- myPage HSt ? (Html,HSt)
- So, a wrapper function is defined
- doHtml (HSt ? (Html,HSt)) ? World ? World
-
16General Structure of a Clean Web application
- module example
- import StdEnv, StdHtml
- Start world doHtml helloWorldPage world
- helloWorldPage hst
- mkHtml "Hello World Example"
- Txt "Hello World" hst
- mkHtml title tags hst (Html (Head Hd_Std
Std_Title s ) - (Body tags)
- ,hst)
17General Structure of a Clean Web application
- helloWorldPage hst
- mkHtml "Hello World Example"
- Txt "Hello World" hst
18What did we gain with our ADT definition ?
- Disadvantage
- Slightly more verbose than plain Html, caused by
restrictions of an ADT - Advantage
- We have at least the expressive power of Html
- Everything is typed, so many html errors cannot
be made anymore - ADT is a handy Html grammar for beginners
- Full power of Clean, let's use it.
19Overview of the talk
- Cleans generic Graphical Editor Components
- Architecture Web applications ltgt Architecture
normal Clean application - Generation of Html code
- Automatic Generation of Html code for any Clean
type - Automatic Generation of simple interactive forms
for any Clean type - Separating Data from Views allowing to make any
kind of form - Implementation
- Arrows
- Conclusion Future Research
20Add ability to show any type
- toHtml a ? BodyTag gForm a
- toHtml converts any Clean type to Html code using
the generic function gForm -
21Add ability to show any type
showBalancedTreePage hst mkHtml "Balanced
Tree" H1 "Balanced Tree" , toHtml
(fromListToBalTree 1..5) hst Tree a
Node (Tree a) a (Tree a) Leaf derive gForm
Tree
22Overview of the talk
- Cleans generic Graphical Editor Components
- Architecture Web applications ltgt Architecture
normal Clean application - Generation of Html code
- Automatic Generation of Html code for any Clean
type - Automatic Generation of simple interactive forms
for any Clean type - Separating Data from Views allowing to make any
kind of form - Implementation
- Arrows
- Conclusion Future Research
23Automatic creation of Interactive Forms
- mkEditForm FormId d HSt ? (Form d, HSt)
gHTML d - FormId
- id String // id uniquely identifying
the form - , lifespan Lifespan // lifespan of form
- , mode Mode // editable or not
-
- Lifespan
- Persistent // form will live "forever" in a
file - Session // form will live a session long
- Page // form will live a page long
- Mode
- Edit // an editable form
- Display // a non-editable form
- Form d
- changed Bool // the user has edited the
form - , value d // current value in data domain
(the feel) - , form BodyTag // html code to create the
form (the look) -
24Example an editable record
- Person name String
- , address String
- , city String
-
- initPerson name "", address "" , city
"" - personPage hst
- (person,hst) mkEditForm (nFormId "person")
initPerson hst - mkHtml "Person"
- H1 "Person"
- , BodyTag person.form
- hst
- nFormId s id s, lifespan Page, mode
Edit - ndFormId s id s, lifespan Page, mode
Display
25Example an editable tree
- treePage hst
- (tree,hst) mkEditForm (nFormId "tree") (Node
Leaf 1 Leaf) hst - mkHtml "Simple Tree"
- H1 "Simple Tree"
- , BodyTag tree.form
- hst
26Example an editable list converted to a balanced
tree
- listToBalancedTreePage hst
- (list,hst) mkEditForm (nFormId "list") 1
hst - mkHtml "List to Balanced Tree"
- H1 "List to Balanced Tree"
- , BodyTag list.form
- , Br
- , toHtml (fromListToBalTree list.value)
- hst
27Example showing a list as an vertical table
- vertlistForm FormId a HSt ? (Form
a,HSt) gHTML a - vertlistForm _ hst (changed
False,value ,form ,hst) - vertlistForm formid xxs hst
- (nxs,hst) vertlistForm formid xs hst
- (nx, hst) mkEditForm nformid x hst
- ( changed nxs.changed nx.changed
- ,value nx.value nxs.value
- ,form nx.form ltgt nxs.form
- ,hst )
- where
- nformid formid id formid.id toString
(length xs)
28Example taken the sum of a table
- vertTablePage hst
- (vtable,hst) vertlistForm (nFormId
"vertlist") 1..5 hst - mkHtml "Vertical Table"
- H1 "Vertical Table"
- , BodyTag vtable.form
- , toHtml (sum vtable.value)
- hst
29Simple Spreadsheet
- spreadsheet hst
- (tablef, hst) table_hv_Form (nFormId
"table") (inittable 8 10) hst - (rowsumf,hst) vertlistForm (ndFormId "rsum")
(rowsum tablef.value) hst - (colsumf,hst) horlistForm (ndFormId "csum")
(colsum tablef.value) hst - (totsumf,hst) mkEditForm (ndFormId "tsum")
(sum (rowsum tablef.value)) hst - mkHtml "Spreadsheet"
- H1 "Simple Spreadsheet Example "
- , tablef.form ltgt rowsumf.form
- , colsumf.form ltgt totsumf.form
- hst
- rowsum table map sum table
- colsum table map sum (transpose table)
- transpose table table!!i!!j \\ i lt-
0..(length table) - 1 - \\ j lt- 0..length (table!!0) - 1
-
- inittable n m i..in \\ i lt- 0,n1 ..
nm1
30Simple Spreadsheet
31Spreadsheet using toHtml(Form)
- spreadsheet hst
- (table, hst) table_hv_Form (nFormId "table")
(inittable 8 10) hst - mkHtml "Spreadsheet"
- H1 "Simple Spreadsheet Example "
- , table.form ltgt rowsumF table.value
- , colsumF table.value ltgt totsumF table.value
- hst
- rowsumF table toHtmlForm (vertlistForm
(ndFormId "rsum") (rowsum table)) - colsumF table toHtmlForm (horlistForm
(ndFormId "csum") (colsum table)) - totsumF table toHtmlForm (mkEditForm (ndFormId
"tsum") (sum (rowsum table))) - toHtmlForm (HSt ? (Form a,HSt)) ? BodyTag
gHTML a
32Spreadsheet defined in Monadic Style
- spreadsheet
- table_hv_Form (nFormId "table") (inittable 8
10) gtgt \table ? - vertlistForm (ndFormId "rsum") (rowsum
table.value) gtgt \rowsum ? - horlistForm (ndFormId "csum") (colsum
table.value) gtgt \colsum ? - mkEditForm (ndFormId "tsum") (sum (rowsum
table.value)) gtgt \totsum ? - mkHtmlM "Spreadsheet"
- H1 "Spreadsheet Example "
- , table.form ltgt rowsum.form
- , colsum.form ltgt totsum.form
-
- HStM a HSt -gt (a, HSt)
- (gtgt) infixr 5 (HStM .a) (.a -gt HStM .b) -gt
HStM .b - mkHtmlM String BodyTag -gt HStM Html
33What did we gain so far ?
- Advantage
- We obtain an editor for free for (almost) any
Clean type -
- No low level Html form handling required
- We want to do more
- Editable forms which contents depend on value of
other forms - Make a complete separation between "data" and
"view" - One function that can fulfil all wishes
34Overview of the talk
- Cleans generic Graphical Editor Components
- Architecture Web applications ltgt Architecture
normal Clean application - Generation of Html code
- Automatic Generation of Html code for any Clean
type - Automatic Generation of simple interactive forms
for any Clean type - Separating Data from Views allowing to make any
kind of form - Implementation
- Arrows
- Conclusion Future Research
35Separation of Data Model and View Model
- Instead of
- mkEditForm FormId d HSt ? (Form d, HSt)
gHTML d - We define the more general function
- mkViewForm FormId d (ViewBimap d v) HSt ?
(Form d, HSt) gHTML v - ViewBimap d v
- toForm d (Maybe v) ? v // converts
data to view domain - , updForm Bool v ? v // update, True when
form edited - , fromForm Bool v ? d // back to data
domain - , resetForm Maybe (v ? v) // reset view
option -
-
36mkEditForm is just a simple variant of mkViewForm
- mkEditForm FormId d HSt ? (Form d,HSt)
gHtml d - mkEditForm formid data hst mkViewForm formid
data - toForm toFormid
- , updForm \_ d ? d
- , fromForm \_ d ? d
- , resetForm Nothing hst
- toFormid d Nothing d
- toFormid d (Just old_d) old_d
37Counter example
- counterForm FormId a HSt ? (Form a,HSt)
, -, one, gHtml a - counterForm name i hst mkViewForm name i
counterView hst - counterView toForm \n ? toFormid
(n,down,up) - , updForm updCounter
- , fromForm \_ (n,_,_) ? n
- , resetForm Nothing
-
- where
- updCounter _ (n,Pressed,_) (n - one,down,up)
- updCounter _ (n,_,Pressed) (n one,down,up)
- updCounter _ else else
- down LButton (defpixel / 6) "-"
- up LButton (defpixel / 6) ""
38Counter Example
- counterExamplePage hst
- (counter1,hst) counterForm (nFormId
"counter1") 0 hst - (counter2,hst) counterForm (nFormId
"counter2") 0 hst - mkHtml "Counter Example"
- H1 "Counter Example"
- , BodyTag counter1.form
- , BodyTag counter2.form
- , toHtml (counter1.value counter2.value)
- hst
39mkViewForm variants mkSelfForm for self
correcting forms
- mkSelfForm FormId d (d ? d) HSt ? (Form
d,HSt) gHtml d - mkSelfForm formid initdata cbf hst mkViewForm
formid data - toForm toFormid
- , updForm update
- , fromForm \_ d ? d
- , resetForm Nothing hst
- where
- update True newval cbf newval
- update _ val val
40Self Balancing Tree
- selfBalancingTreePage hst
- (balancedtree,hst) mkSelfForm (nFormId
"BalancedTree") - (fromListToBalTree 0) balanceTree hst
- mkHtml "Balanced Tree"
- H1 "Balanced Tree"
- , BodyTag balancedtree.form
- hst
41mkViewForm variants a Store
- mkStoreForm FormId d (d ? d) HSt ? (Form
d,HSt) gHtml d - mkStoreForm formid data cbf hst
- mkViewForm formid data toForm toFormid
- , updForm \_ d ? cbf d
- , fromForm \_ d ? d
- , resetForm Nothing hst
42Page Visitors Counter
- pageCount hst
- (pagecount,hst) mkStoreForm (pFormId
"pageCount") 0 (\n ? inc n) hst - mkHtml "Balanced Tree"
- H1 "Page Count"
- , Txt ("You are visitor nr " toString
pagecount.value) - hst
- pdFormId s id s, lifespan Persistent, mode
Display
43Types with special views
- Button
- Pressed // button pressed
- LButton Int String // label button, size in
pixels, label of button - PButton (Int,Int) String // picture button,
(height,width), ref to picture - CheckBox
- CBChecked String // checkbox checked
- CBNotChecked String // checkbox not checked
- RadioButton
- RBChecked String // radiobutton checked
- RBNotChecked String // radiobutton not checked
- PullDownMenu
- PullDown (Int,Int) (Int,String) //
pulldownmenu (number visible,width) - (item chosen,menulist)
44Calculator
- TableFuncBut FormId (Button, a ? a) HSt ?
(Form (a ? a) ,HSt) - calcbuttons (Button, (Int,Int) ? (Int,Int)
- calcbuttons (but "7",set 7), (but
"8",set 8), (but "9",set 9) - , (but "4",set 4), (but "5",set 5),
(but "6",set 6) - , (but "1",set 1), (but "2",set 2),
(but "3",set 3) - , (but "0",set 0), (but "C",clear)
- , (but "",app ()), (but "-",app (-)),
(but "",app ()) -
- where
- set ni (mem,i) (mem, i10 ni)
- clear (mem,i) (mem,0)
- app fun (mem,i) (fun mem i , 0)
- but i LButton (defpixel / 3) i
45Calculator
- calculator hst
- (calcfun,hst) TableFuncBut (nFormId
"calcbut") calcbuttons hst - (display,hst) mkStoreForm (ndFormId
"display") (0,0) calcfun.value hst mkHtml
"Calculator" - H1 "Calculator Example "
- , mem display lt..gt input display
- , toBody calcfun
- hst
- where
- mem display toHtml (fst (display.value))
- input display toHtml (snd (display.value))
46Simple Login Administration (I)
- Login
- loginName String
- , password String
-
- loginHandler hst
- (login,hst) mkEditForm (sFormId "login")
(mklogin "" "") hst - (loginDatabase,hst) loginStore id hst
- (page,hst) if (isMember login.value
loginDatabase.value) - (memberPage login hst)
- (loginPage login hst)
- mkHtml "login test"
- BodyTag page hst
- where
- loginStore upd hst mkStoreForm (pFormId
"logindatabase") upd hst - mklogin name password loginName name,
password password
47Simple Login Administration (II)
- loginPage login hst
- (addlogin,hst) addLoginButton login.value
hst - (loginDatabase,hst) loginStore (addLogin
login.value addlogin.changed) hst - isMember login.value loginDatabase.value
memberPage login hst - ( Txt "Please log in ..."
- , Br, Br
- , BodyTag login.form
- , Br
- , BodyTag addlogin.form
- , hst)
- addLoginButton value hst ListFuncBut False
(formid "addlogin") addbutton hst - addbutton (LButton defpixel "addLogin", id)
- formid if (value.loginName ltgt ""
value.password ltgt "") nFormId ndFormId
48Simple Login Administration (III)
- memberPage login hst
- ( Txt ("Welcome " login.value.loginName)
- , hst)
49Overview of the talk
- Cleans generic Graphical Editor Components
- Architecture Web applications ltgt Architecture
normal Clean application - Generation of Html code
- Automatic Generation of Html code for any Clean
type - Automatic Generation of simple interactive forms
for any Clean type - Separating Data from Views allowing to make any
kind of form - Implementation
- Arrows
- Conclusion Future Research
50Architecture Clean application for the Web
Serialized State of Forms Changed input
Html Code Serialized State of Forms
Serialized State of Forms
51Generic functions used
- doHtml (HSt ? (Html,HSt)) ? World ?
World - mkViewForm FormId d (ViewBimap d v) HSt ?
(Form d, HSt) gHTML v - class gHtml v gForm, gUpd,
gPrint, gParse v - The following generic functions are used
- gPrint can serialize a value of any
(first-order) Clean type - to store a form state in a page, file or
database - gParse can de-serialize a value of any
(first-order) Clean type - to re-construct a form state
- gUpd can update a value of any type given any
change made in a form - gForm can create an interactive Html form for
any value of any type - gHpr can generate html code given a value of
type Html
52Consider the following types
- List a Nil
- Cons a (List a)
- Rose a Rose a (List (Rose a))
- Tree a b Tip a
- Bin b (Tree a b) (Tree a b)
53Overloaded equality
- class infix 4 t t t ? Bool
- instance (List a) a
- where
- () Nil Nil True
- () (Cons x xs) (Cons y ys) x y xs
ys - () _ _
False - instance (Rose a) a
- where
- () (Rose x xs) (Rose y ys) x y xs
ys - instance (Tree a b) a b
- where () (Tip x) (Tip y) x
y - () (Bin x ltx rtx) (Bin y lty rty) x
y ltx lty rtx rty - () _ _ False
54The idea of generic programming
List a
List a
List b
Rose a
Rose a
Rose b
55The idea of generic programming
List a
List a
List b
Generic
Generic Type
Generic Type
Rose a
Rose a
Rose b
56The idea of generic programming
List a
List a
List b
fromList
toList
Generic
Generic Type
Generic Type
toRose
fromRose
Rose a
Rose a
Rose b
57Generic Programming in Clean
- Any type in Clean can be encoded in a Generic
Type - A Generic Type is not one type, but a combination
of types - Unit type, binary sums and products type
- UNIT UNIT
- PAIR a b PAIR a b
- EITHER a b LEFT a RIGHT b
- One generic function works for all types
- Overloaded functions can be defined generically
58Generic equality
- generic gEq a a a -gt Bool
- gEqInt x y x y
- gEqBool x y x y
- gEqReal x y x y
- gEqUNIT UNIT UNIT True
- gEqPAIR eqa eqb (PAIR a1 b1) (PAIR a2
b2) eqa a1 a2 eqb b1 b2 - gEqEITHER eqa eqb (LEFT a1) (LEFT a2)
eqa a1 a2 - gEqEITHER eqa eqb (RIGHT b1) (RIGHT b2)
eqb b1 b2 - gEqEITHER eqa eqb _ _ False
59Types of these generic functions
- generic gPrint a a ?String
- generic gParse a String ? Maybe a
- generic gUpd a UpdMode a ? (UpdMode,a)
- generic gForm a FormId a HSt -gt (Form a,
HSt) - generic gHpr a File a ? File
60Updating a value
- How can we reconstruct a value that has been
changed interactively ? - We only need to know 3 things
- Which form was it? FormId.id
- What has been changed ?
- Simple case only a few basic cases
-
- Change existing value Int, Real, String, Bool,
- Create new values Constructor
-
- Complication change of form may depend on the
change of others - Where in the form?
- We don't need any knowledge about the html code !
- We only need to know which value has changed
- We just need the position in its generic
representation
61Updating a value (I)
- generic gUpd a UpdMode a ? (UpdMode,a)
- UpdMode UpdSearch UpdValue Pos // search
for position - UpdCreate ConsPos // in generic
representation - UpdDone // copy the remaining expression
- UpdValue UpdI Int // new Integer value
- UpdR Real // new Real value
- UpdB Bool // new Boolean value
- UpdS String // new String value
- UpdC String // new Constructor value
- ConsPos ConsLeft
- ConsRight
- Pos Int
62Updating a value (II)
-
- gUpdInt (UpdSearch (UpdI ni) 0) _
(UpdDone,ni) - gUpdInt (UpdSearch val cnt) i
(UpdSearch val (dec cnt),i) - gUpdInt (UpdCreate p) _ (UpdCreate
p,0) - gUpdInt mode i (mode,i)
-
63Cycle of a Clean Web Application 1 Read the
stored states
- set of states in stores change in a form
-
- (idString,viewString)
(idString,updString,posString)
64Cycle of a Clean Web Application 1 Read the
stored states
- set of states in stores change in a form
-
- (idString,viewString)
(idString,updString,posString) - gParse de-serialize
- (idString,viewVi) (idString,updUp
dValue, posInt) -
-
65Cycle of a Clean Web Application 1 Read the
stored states
- set of states in stores change in a form
-
- (idString,viewString)
(idString,updString,posString) - gParse de-serialize
- (idString,viewVi) (idString,updUp
dValue, posInt) -
- gUpd update states
- (idString,updviewVi), (changedBool)
-
66Cycle of a Clean Web Application 2 calculate new
forms
- (idString,updviewVi), (changedBool)
-
-
67Cycle of a Clean Web Application 2 calculate new
forms
- (idString,updviewVi), (changedBool)
-
- ViewBimap Mi ? Vi calculate effects for
programmer - (idString,nextviewVi), (valueMi
,changedBool) -
68Cycle of a Clean Web Application 2 calculate new
forms
- (idString,updviewVi), (changedBool)
-
- ViewBimap Mi ? Vi calculate effects for
programmer - (idString,nextviewVi), (valueMi
,changedBool) - gForm generate the forms for the views
-
- (idString,nextviewVi), (form Html,
valueMi, changedBool) -
-
69Cycle of a Clean Web Application 2 calculate new
forms
- (idString,updviewVi), (changedBool)
-
- ViewBimap Mi ? Vi calculate effects for
programmer - (idString,nextviewVi), (valueMi
,changedBool) - gForm generate the forms for the views
-
- (idString,nextviewVi), (form Html,
valueMi, changedBool) -
- user page additional user defined Html code
- (idString,nextviewVi), pageHtml, (form
Html, valueMi, changedBool)
70Cycle of a Clean Web Application 3 store the
states
- (idString,nextviewVi), pageHtml,(form
Html, valueMi, changedBool) -
-
71Cycle of a Clean Web Application 3 store the
states
- (idString,nextviewVi), pageHtml,(form
Html, valueMi, changedBool) -
- gPrint serialize values of Clean types
- (idString,nextviewString) , page form
Html -
72Cycle of a Clean Web Application 3 store the
states
- (idString,nextviewVi), pageHtml,(form
Html, valueMi, changedBool) -
- gPrint serialize values of Clean types
- (idString,nextviewString) , page form
Html - gHpr generate Html code
- (idString,viewString)
(idString,updString,posString) - set of states in stores set of possible
changes - page form Htmlstrings
73Cycle of a Clean Web Application 3 store the
states
-
-
-
- (idString,viewString)
(idString,updString,posString) - set of states in stores set of possible
changes - page form Htmlstrings
74Overview of the talk
- Cleans generic Graphical Editor Components
- Architecture Web applications ltgt Architecture
normal Clean application - Generation of Html code
- Automatic Generation of Html code for any Clean
type - Automatic Generation of simple interactive forms
for any Clean type - Separating Data from Views allowing to make any
kind of form - Implementation
- Arrows
- Conclusion Future Research
75Simple Spreadsheet
- spreadsheet hst
- (tablef, hst) table_hv_Form (nFormId
"table") (inittable 8 10) hst - (rowsumf,hst) vertlistForm (ndFormId "rsum")
(rowsum tablef.value) hst - (colsumf,hst) horlistForm (ndFormId "csum")
(colsum tablef.value) hst - (totsumf,hst) mkEditForm (ndFormId "tsum")
(sum (rowsum tablef.value)) hst - mkHtml "Spreadsheet"
- H1 "Simple Spreadsheet Example "
- , tablef.form ltgt rowsumf.form
- , colsumf.form ltgt totsumf.form
- hst
76Wiring of Forms
- Wiring of form editors can be done using
- - the construct
- - in a monadic style
- - with special "wiring" combinators Arrows
-
77Html Form Arrows
- A FormCircuit is a circuit of editors, displays,
and functions with input a and output b - FormCircuit a b
- Basic Circuits Components
- edit FormId ? FormCircuit a a gHtml a
- display FormId ? FormCircuit a a gHtml
a - store FormId a ? FormCircuit (a ? a) a
gHtml a
78Basic Circuit Arrow Combinators
- arr (a ? b) ? FormCircuit a b
- (gtgtgt) infixr 1 (FormCircuit a b) (FormCircuit
b c) ? FormCircuit a c - first (FormCircuit a b) ? FormCircuit (a,
c) (b, c)
79Derived Circuit Arrow Combinators
- second (FormCircuit a b) ? FormCircuit (c,a)
(c,b) - second f arr swap gtgtgt first g gtgtgt arr swap
- where swap t (snd t, fst t)
- () infixr 3 (FormCircuit a b) (FormCircuit
c d) ? FormCircuit (a, c) (b, d) - () l r first l gtgtgt second r
- () infixr 3 (FormCircuit a b) (FormCircuit
a c) ? FormCircuit a (b, c) - () l r arr (\x ? (x, x)) gtgtgt (l r)
80Special Circuit Arrow Combinators
-
- feedback (FormCircuit a b) (FormCircuit b a)
? (FormCircuit a b) - self (a ? a) (FormCircuit a a) ?
FormCircuit a a - lift FormId (FormEditor a b) ? (FormCircuit
a b) - FormEditor a b FormId a HSt ? (Form
b,HSt)
81Form Circuits as Form Editor
- Any Circuit a b of Forms can be used as Form
Editor - startCircuit (FormCircuit a b) a HSt ? (Form
b,HSt) - This can be used as alternative for wiring
editors.
82Self Balancing Tree with traditional plumbing
- selfBalancingTreePage hst
- (balancedtree,hst) mkSelfForm (nFormId
"BalancedTree") - (fromListToBalTree 0) balanceTree hst
- mkHtml "Balanced Tree"
- H1 "Balanced Tree"
- , BodyTag balancedtree.form
- hst
83Self Balancing Tree using Arrow Combinators
- selfBalancingTreePage hst
- (balancedtree,hst) startCircuit mycircuit
(fromListToBalTree 0) hst - mkHtml "Balanced Tree"
- H1 "Balanced Tree"
- , BodyTag balancedtree.form
- hst
- where
- mycircuit feedback (edit (nFormId
"BalancedTree")) (arr balanceTree)
Tree
Tree
balanceTree
84Simple Spreadsheet
85Simple Spreadsheet with traditional plumbing
- spreadsheet hst
- (tablef, hst) table_hv_Form (nFormId
"table") (inittable 8 10) hst - (rowsumf,hst) vertlistForm (ndFormId "rsum")
(rowsum tablef.value) hst - (colsumf,hst) horlistForm (ndFormId "csum")
(colsum tablef.value) hst - (totsumf,hst) mkEditForm (ndFormId "tsum")
(sum (rowsum tablef.value)) hst - mkHtml "Spreadsheet"
- H1 "Simple Spreadsheet Example "
- , tablef.form ltgt rowsumf.form
- , colsumf.form ltgt totsumf.form
- hst
86Simple Spreadsheet using Arrow Combinators
- spreadsheet hst
- (circuitf, hst) startCircuit mycircuit
(inittable 8 10) hst - tableform,rowsumform,colsumform,totsumform_
circuitf.form - mkHtml "Spreadsheet"
- H1 "Spreadsheet Example "
- , tableform lt..gt rowsumform
- , colsumform lt..gt totsumform
- hst
- where
- mycircuit lift (nFormId "table") table_hv_Form
- gtgtgt ( (arr rowsum gtgtgt lift (nFormId "rsum")
vertlistForm) - (arr colsum gtgtgt lift (nFormId "csum")
horlistForm) - )
- gtgtgt arr (sum o fst)
- gtgtgt display (nFormId "tsum")
87Arrow Class (Hughes)
- class Arrow arr
- where
- arr (a ? b) ? arr a b
- (gtgtgt) infixr 1 (arr a b) (arr b c) ? arr a c
- first (arr a b) ? arr (a, c) (b, c)
-
88Derived Arrow Combinators
- second (arr a b) ? arr (c,a) (c,b) Arrow
arr - second f arr swap gtgtgt first g gtgtgt arr swap
- where
- swap t (snd t, fst t)
- () infixr 3 (arr a b) (arr c d) -gt arr (a,
c) (b, d) Arrow arr - () l r first l gtgtgt second r
-
89Functions are arrows
- instance Arrow (?)
- where
- arr (a ? b) ? (a ? b)
- arr f f
- (gtgtgt) infixr 1 (a ? b) (b ? c) ? (a ? c)
- (gtgtgt) f g g o f
- first (a ? b) ? ((a, c) ? (b, c))
- first f \(x, y) ? (f x, y)
-
90Overview of the talk
- Cleans generic Graphical Editor Components
- Architecture Web applications ltgt Architecture
normal Clean application - Generation of Html code
- Automatic Generation of Html code for any Clean
type - Automatic Generation of simple interactive forms
for any Clean type - Separating Data from Views allowing to make any
kind of form - Implementation
- Arrows
- Conclusion Future Research
91Types with special views
- Button
- Pressed // button pressed
- LButton Int String // label button, size in
pixels, label of button - PButton (Int,Int) String // picture button,
(height,width), ref to picture - CheckBox
- CBChecked String // checkbox checked
- CBNotChecked String // checkbox not checked
- RadioButton
- RBChecked String // radiobutton checked
- RBNotChecked String // radiobutton not checked
- PullDownMenu
- PullDown (Int,Int) (Int,String) //
pulldownmenu (number visible,width) - (item chosen,menulist)
92Specialization (I)
- Example in the data domain/model we have the
following type - Date Date Int Int Int
- In the view domain/model we want to show this
everywhere as - ViewOfDate ViewDate PullDownMenu
PullDownMenu PullDownMenu - In fact we want to redefine the default editor
for type Date - This is called specialization.
- So, the user has to give a definition of the
generic function that can create forms - generic gForm d (FormEditor d d)
- FormEditor a b FormId a HSt -gt (Form
b,HSt)
93Specialization (II) define a bimap between data
and view
- Bimap a b map_to (a -gt b), map_from
(b -gt a) - myDateBimap Bimap Date ViewOfDate
- myDateBimap map_to toPullDown, map_from
fromPullDown - toPullDown (Date day month year) (ViewDate
pddays pdmonths pdyears) - where
- pddays PullDown (1,defpixel/2)
(day-1,toString i \\ i lt- 1..31) - pdmonths PullDown (1,defpixel/2)
(month-1,toString i \\ i lt- 1..12) - pdyears PullDown (1,2defpixel/3)
(year-1,toString i \\ i lt- 2005..2010) -
- fromPullDown (ViewDate pddays pdmonths pdyears)
- Date (convert pddays) (convert pdmonths)
(convert pdyears) - where
- convert x toInt (toString x)
94Specialization (III) mkBimapEditor
- mkBimapEditor FormId d (Bimap d v) HSt ?
(Form d,HSt) gHtml d - mkBimapEditor formid data bimap hst
- mkViewForm formid data toForm \d v ?
case v of Nothing ? map_to d - Just v ? v
- , updForm \_ v ? v
- , fromForm \_ v ? map_from v
- , resetForm Nothing hst
95Specialization (IV) re-assign the default form
editor
- gForm Date formid date hst specialize
myeditor formid date hst - where
- myeditor formid date hst mkBimapEditor formid
date bimap hst - The function "specialize" replaces the default
generic editor by your editor. - specialize (FormEditor d d) FormId d HSt -gt
(Form d,HSt) gUpd a
96Conclusions Future work
- Done
- High-level easy-to-read specification of
complicated web forms - A Web application looks like an "ordinary"
application - Good separation between data and view
- One function does it all !
- Nice, relative simple implementation based on
generic functions - Arrow combinators are defined for constructing
Form circuits - Specialisation possible that allows to redefine
any view of any type - To do
- (de)-serialize high order functions in state
(using dynamics) - polish implementation, extend library
- unify Cleans GEC Web GEC definitions and
implementation - define formal semantics and proof properties of
GEC Forms - use GAST to test web applications automatically
- find better solutions for formid identifiers