[web-devel] The promising world of Monadic formlets

Alberto G. Corona agocorona at gmail.com
Wed Jun 19 22:35:35 CEST 2013


Hi,

This is just to let you know the promising results of some experimentation:

Formlets are about applicative instances, but what about monadic instances?
What a Monad instance of formlets means? I recently experimented with this
and the results are very interesting and powerful- It mixes the best of web
forms, with the flexibility of console applications. ???!!!!!!


Althoug this example is for the formlets of the MFlow
<https://github.com/agocorona/MFlow>framework , it can be ported to other
formlet implementations. Although the MFLow formlets include web formatting
that is not supported in other formlets implementations. Static HTML
templating don´t work well with monadic formlets, so it is important to
include the formatting as a  part of the computation:

import MFlow.Wai.Blaze.Html.All

dynamicForm= wform $ do
      (n,s) <- (,) <- p << "Who are you?"
                   ++> getString Nothing  <! hint "name"     <++ br
                   <*> getString Nothing  <! hint "surname"  <++ br
                   <** submitButton "ok" <++ br

      flag <- b << "do you " ++> getRadio[radiob "work?",radiob "study?"]
<++ br

      r<-case flag of
         "work" -> pageFlow "l"
                     $ Left  <- b << "do you enjoy your work? "
                                ++> getBool True "yes" "no"
                                <** submitButton "ok"  <++ br

         "study"-> pageFlow "r"
                     $ Right <- b << "do you study in "
                                  ++> getRadio[radiob "University"
                                         ,radiob "High School"]

      p << ("You are "++n++" "++s) ++>
       case r of
         Left fl ->   p << ("You work and it is " ++ show fl ++ " that you
enjoy your work")
                        ++> noWidget

         Right stu -> p << ("You study at the " ++ stu)
                        ++> noWidget


hint s= [("placeholder",s)]
onClickSubmit= [("onclick","this.form.submit()")]
radiob s n= text s ++> setRadio s n <! onClickSubmit

Here wform, getBool, getString , getRadio etc are formlet elements

The first sentence is an applicative composition that generate a 2 tuple,
to show that applicative and monadic can be mixed.  the operations ++> add
html to the formlet. the operatior <! add attributes to the formlet
element.. noWidget is a dumb formlet that does not validate.

The second monadic statement is an election between two options. The beauty
of the monadic instance is that the rest of the form can vary depending on
the previous answers.  Since the formlets validate the input, unless the
election is made, the radio will not validate, so the monadic
execution will be aborted beyond any unanswered question, so nothing will
appear after the question. The rest of the form will appear when the user
choose one of the two options. once one or the other option is chosen, then
another binary question is presented. (either he likes his work or where he
study).  When the questions are finised, the results are presented.
I hope that you get the idea. The benefit is not only the familiar coding
and presentation of a sequential console application: Since the form
encloses all the fields, At any time the user can change previous inputs
and the form will reflect these changes. For example if the user change
from work to study (second statements) the "where do you study will appear
and the work related questions and answers will disappear. That is
wonderfully useful for heavily interactive applications.

There is  a problem however and it is the issue of the formlet identifiers.
Unlike in an applicative presentation, now the number and type of the
formlets will vary, so the response to a previous form create a new kind
of form, and the post response can be misinterpreted. To avoid that ,
the  pageFlow call creates fixed field labels for each branch of execution.

I will release a version of MFlow that support this kind of monadic
composition of fomlets, but In essence it is nothing but to add Monad
instance to formlets. A single server procedure, that executes the formlet
code can support all the interaction so any framework can do it. The
usability of that is huge:It is possible to interact in a web page in a
console style with questions and answers with the versatitly of a dynamic
foms: Any modification in the form change the subsequent flow of
interaction. Another application of this monadic style is to ease multistep
processes such are registration, check-out and payment ad so on. Even a
entire interactive dynamic application can be coded in a single page.

And no javascript is needed!.


To run this formlet in MFlow:

main=do
  addMessageFlows
       [(""    , transient $ runFlow  $ ask dynamicForm )]

   wait $ run port waiMessageFlow


This video show how the presentation of this example vary with the user
input:

http://youtu.be/DryBQc9agFg


I hope that you find the idea interesting.  If you want to experiment
with this in MFlow, I have to say that the implementation of this feature
is in an early stage. The code is in the head branch

https://github.com/agocorona/MFlow/tree/head



Alberto.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/web-devel/attachments/20130619/fff6e083/attachment.htm>


More information about the web-devel mailing list