Wojtek Narczyński | 12 Aug 00:16 2014
Picon

The Good, the Bad and the GUI

Dear All,

Haskell is great for great many areas, let me name just two: - parsers, 
translators, interpreters, compilers; highly concurrent systems.

Haskell is however not great for GUIs. I've been thinking a little why 
this is so. I think one of the reasons might be that in Haskell it is 
unusual to deal with data that is incomplete or otherwise erroneous. Let 
me try to explain, what I mean, by example. If you declare Person class 
in Java, you automatically get a thingy that you can readily use in UI 
construction, because all the fields can temporarily be null, even the 
required ones. In Haskell you'd need two data types: the usual proper 
Haskell data type, and another which wraps every field in Maybe, 
facilitates editing, validation, etc. Perhaps it would be possible to 
generate one data type from the other, or generate both from a common 
specification.

Let me write the same thing in other words. It is not controversial to 
say on this list that specifying what is correct means, is a good idea. 
But for GUIs, in addition to the strong type, you need another relaxed 
type to hold the values temporarily, until the human manages to deliver 
correct data, often by trial and error.

Comments welcome.

--

-- 
Kind regards,
Wojtek Narczyński

_______________________________________________
(Continue reading)

Brandon Allbery | 12 Aug 00:25 2014
Picon

Re: The Good, the Bad and the GUI

On Mon, Aug 11, 2014 at 6:16 PM, Wojtek Narczyński <wojtek <at> power.com.pl> wrote:
Let me write the same thing in other words. It is not controversial to say on this list that specifying what is correct means, is a good idea. But for GUIs, in addition to the strong type, you need another relaxed type to hold the values temporarily, until the human manages to deliver correct data, often by trial and error.

I think there are far larger issues to deal with first: you need to have a sensible connection from Haskell to a GUI before you can worry about getting data across it. At the moment, we have either mostly procedural interfaces to common procedural toolkits (WxHaskell, gtk2hs) or a number of still largely experimental FRP interfaces.

It is not particularly difficult to deal with the step that you highlight once we have solved the basic interface to the GUI; you can do it with Template Haskell, or generics, or lens, or with semi-typed interfaces between Haskell and the GUI (for example, I can see Aeson sitting in this layer). But figuring out how to work it in depends on knowing what we're working it into.

--
brandon s allbery kf8nh                               sine nomine associates
allbery.b <at> gmail.com                                  ballbery <at> sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Alberto G. Corona | 12 Aug 00:53 2014
Picon

Re: The Good, the Bad and the GUI

I think that the GUI people hace to embrace the formlet concept, used in HTML interfaces sooner better than later. The GUI development has lost the train by trying to interface C libraries that are decades old. The reactive solutions complicates the problem rather than to simplify it. That means that they are not the correct paradigm.


2014-08-12 0:25 GMT+02:00 Brandon Allbery <allbery.b <at> gmail.com>:
On Mon, Aug 11, 2014 at 6:16 PM, Wojtek Narczyński <wojtek <at> power.com.pl> wrote:
Let me write the same thing in other words. It is not controversial to say on this list that specifying what is correct means, is a good idea. But for GUIs, in addition to the strong type, you need another relaxed type to hold the values temporarily, until the human manages to deliver correct data, often by trial and error.

I think there are far larger issues to deal with first: you need to have a sensible connection from Haskell to a GUI before you can worry about getting data across it. At the moment, we have either mostly procedural interfaces to common procedural toolkits (WxHaskell, gtk2hs) or a number of still largely experimental FRP interfaces.

It is not particularly difficult to deal with the step that you highlight once we have solved the basic interface to the GUI; you can do it with Template Haskell, or generics, or lens, or with semi-typed interfaces between Haskell and the GUI (for example, I can see Aeson sitting in this layer). But figuring out how to work it in depends on knowing what we're working it into.

--
brandon s allbery kf8nh                               sine nomine associates
allbery.b <at> gmail.com                                  ballbery <at> sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe




--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 12 Aug 00:57 2014
Picon

Re: The Good, the Bad and the GUI


On 12.08.2014 00:53, Alberto G. Corona wrote:
> I think that the GUI people hace to embrace the formlet concept, used 
> in HTML interfaces sooner better than later. The GUI development has 
> lost the train by trying to interface C libraries that are decades 
> old. The reactive solutions complicates the problem rather than to 
> simplify it. That means that they are not the correct paradigm.
>
I'm mainly interested in HTML/JS GUIs. Perhaps I should have stated it 
explicitly upfront.
Alberto G. Corona | 12 Aug 01:14 2014
Picon

Re: The Good, the Bad and the GUI

Wojtek. What you say is exactly what has been solved time ago by fomlets in Web interfaces.  There are many formlet library and almost all haskell web framework use formlets.


2014-08-12 0:57 GMT+02:00 Wojtek Narczyński <wojtek <at> power.com.pl>:

On 12.08.2014 00:53, Alberto G. Corona wrote:
I think that the GUI people hace to embrace the formlet concept, used in HTML interfaces sooner better than later. The GUI development has lost the train by trying to interface C libraries that are decades old. The reactive solutions complicates the problem rather than to simplify it. That means that they are not the correct paradigm.

I'm mainly interested in HTML/JS GUIs. Perhaps I should have stated it explicitly upfront.



--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Alberto G. Corona | 12 Aug 01:22 2014
Picon

Re: The Good, the Bad and the GUI

But formlets are implemented in the server side.  and you probably think in applications with heavy use of JavaScript for validations, interaction  etc. In this case, there is a formlet implementation in the client side, which is my.. Ahem!... package hplaygroud:



2014-08-12 1:14 GMT+02:00 Alberto G. Corona <agocorona <at> gmail.com>:
Wojtek. What you say is exactly what has been solved time ago by fomlets in Web interfaces.  There are many formlet library and almost all haskell web framework use formlets.


2014-08-12 0:57 GMT+02:00 Wojtek Narczyński <wojtek <at> power.com.pl>:


On 12.08.2014 00:53, Alberto G. Corona wrote:
I think that the GUI people hace to embrace the formlet concept, used in HTML interfaces sooner better than later. The GUI development has lost the train by trying to interface C libraries that are decades old. The reactive solutions complicates the problem rather than to simplify it. That means that they are not the correct paradigm.

I'm mainly interested in HTML/JS GUIs. Perhaps I should have stated it explicitly upfront.



--
Alberto.



--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojciech Narczyński | 12 Aug 21:18 2014
Picon

Re: The Good, the Bad and the GUI

W dniu 2014-08-12 01:22, Alberto G. Corona pisze:
> But formlets are implemented in the server side.  and you probably 
> think in applications with heavy use of JavaScript for validations, 
> interaction  etc. In this case, there is a formlet implementation in 
> the client side, which is my.. Ahem!... package hplaygroud:
>
> https://github.com/agocorona/hplayground
>
Very interesting, please allow a few questions about your approach:

1. Would it be possible to save a snapshot of a paritally filled form on 
the server?
2. Would it be possible to display the sum before the values: 3 = [ 1] + 
[  2] <-- this is rendered HTML, not Haskell?

(I thought I would have more questions, but somehow I can't think of any 
right now...)

--

-- 
Kind regards,
Wojtek
Alberto G. Corona | 12 Aug 21:59 2014
Picon

Re: The Good, the Bad and the GUI




2014-08-12 21:18 GMT+02:00 Wojciech Narczyński <wojtek <at> power.com.pl>:
W dniu 2014-08-12 01:22, Alberto G. Corona pisze:
But formlets are implemented in the server side.  and you probably think in applications with heavy use of JavaScript for validations, interaction  etc. In this case, there is a formlet implementation in the client side, which is my.. Ahem!... package hplaygroud:

https://github.com/agocorona/hplayground

Very interesting, please allow a few questions about your approach:

1. Would it be possible to save a snapshot of a paritally filled form on the server?

hplayground is client side. but by means of Haste.Ajax it is possible to send something to a server.

 do
         r  <- (+) <$> inputAndSend
                     <*> inputAndSend
         p  (show r) ++> noWidget
     where
     inputAndSend= do
         r <- inputInt Nothing `wake` OnKeyPress <++ br
         sendInt  r
         return r
     sendInt i=  send the int trough Haste.Ajax

2. Would it be possible to display the sum before the values: 3 = [ 1] + [  2] <-- this is rendered HTML, not Haskell?

yes, using "at":

 do
        wraw $ div  ! id "result" $ noHtml
         r  <- (+) <$> inputInt Nothing `wake` OnKeyPress <++ br
                     <*> inputInt Nothing `wake` OnKeyPress <++ br

         at "result" Html $ p  (show r) ++> noWidget 
 
(I thought I would have more questions, but somehow I can't think of any right now...)

--
Kind regards,
Wojtek



--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Alberto G. Corona | 12 Aug 22:01 2014
Picon

Re: The Good, the Bad and the GUI

sorry:  instead of

at "result" Html $ ....

is

at "result" Insert $ ....


2014-08-12 21:59 GMT+02:00 Alberto G. Corona <agocorona <at> gmail.com>:



2014-08-12 21:18 GMT+02:00 Wojciech Narczyński <wojtek <at> power.com.pl>:

W dniu 2014-08-12 01:22, Alberto G. Corona pisze:
But formlets are implemented in the server side.  and you probably think in applications with heavy use of JavaScript for validations, interaction  etc. In this case, there is a formlet implementation in the client side, which is my.. Ahem!... package hplaygroud:

https://github.com/agocorona/hplayground

Very interesting, please allow a few questions about your approach:

1. Would it be possible to save a snapshot of a paritally filled form on the server?

hplayground is client side. but by means of Haste.Ajax it is possible to send something to a server.

 do
         r  <- (+) <$> inputAndSend
                     <*> inputAndSend
         p  (show r) ++> noWidget
     where
     inputAndSend= do
         r <- inputInt Nothing `wake` OnKeyPress <++ br
         sendInt  r
         return r
     sendInt i=  send the int trough Haste.Ajax

2. Would it be possible to display the sum before the values: 3 = [ 1] + [  2] <-- this is rendered HTML, not Haskell?

yes, using "at":

 do
        wraw $ div  ! id "result" $ noHtml
         r  <- (+) <$> inputInt Nothing `wake` OnKeyPress <++ br
                     <*> inputInt Nothing `wake` OnKeyPress <++ br

         at "result" Html $ p  (show r) ++> noWidget 
 
(I thought I would have more questions, but somehow I can't think of any right now...)

--
Kind regards,
Wojtek



--
Alberto.



--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 12 Aug 22:51 2014
Picon

Re: The Good, the Bad and the GUI


On 12.08.2014 22:01, Alberto G. Corona wrote:
> sorry:  instead of
>
> at "result" Html $ ....
>
> is
>
> at "result" Insert $ ....
>
Oh, so basically, you create an element and later on replace it with the 
right content. I think it's a hack, but a neat one.

--

-- 
Wojtek
Alberto G. Corona | 12 Aug 23:27 2014
Picon

Re: The Good, the Bad and the GUI

Well, it is not a hack. It is the way hplayground works . normally it rewrite the HTML DOM of the implicit divs that are below  the event source. "at" permits to assign freely that location.


2014-08-12 22:51 GMT+02:00 Wojtek Narczyński <wojtek <at> power.com.pl>:

On 12.08.2014 22:01, Alberto G. Corona wrote:
sorry:  instead of

at "result" Html $ ....

is

at "result" Insert $ ....

Oh, so basically, you create an element and later on replace it with the right content. I think it's a hack, but a neat one.

--
Wojtek



--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 12 Aug 23:42 2014
Picon

Re: The Good, the Bad and the GUI

On 12.08.2014 23:27, Alberto G. Corona wrote:
> Well, it is not a hack. It is the way hplayground works . normally it 
> rewrite the HTML DOM of the implicit divs that are below  the event 
> source. "at" permits to assign freely that location.

Okay, I see.

3. Are you yourself aware of any serious limitations of your approach?

--

-- 
Wojtek
Alberto G. Corona | 13 Aug 00:13 2014
Picon

Re: The Good, the Bad and the GUI

I did the todo application, (see todomvc.com) to check if the concept was expressive and robust enough to do it:


 I think that the model works and the haste compiler works very well too. I don´t know any serious limitation.  "wcallback" generates spurious DOM elements and so on, but that can be fixed. 






2014-08-12 23:42 GMT+02:00 Wojtek Narczyński <wojtek <at> power.com.pl>:
On 12.08.2014 23:27, Alberto G. Corona wrote:
Well, it is not a hack. It is the way hplayground works . normally it rewrite the HTML DOM of the implicit divs that are below  the event source. "at" permits to assign freely that location.

Okay, I see.

3. Are you yourself aware of any serious limitations of your approach?

--
Wojtek



--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 13 Aug 00:56 2014
Picon

Re: The Good, the Bad and the GUI

On 13.08.2014 00:13, Alberto G. Corona wrote:
I did the todo application, (see todomvc.com) to check if the concept was expressive and robust enough to do it:

I have seen the app running, I'm yet to take a look at the code.

 I think that the model works and the haste compiler works very well too. I don´t know any serious limitation.  "wcallback" generates spurious DOM elements and so on, but that can be fixed. 


Great. Overall, I'm impressed. This really looks like a practical way to keep the JS mess under the carpet.

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Rik van der Kleij | 13 Aug 11:05 2014
Picon

Re: The Good, the Bad and the GUI

Maybe you should port hplayground to purescript and virtual-dom :-)


On Wednesday, 13 August 2014 00:13:42 UTC+2, Alberto G. Corona wrote:
I did the todo application, (see todomvc.com) to check if the concept was expressive and robust enough to do it:


 I think that the model works and the haste compiler works very well too. I don´t know any serious limitation.  "wcallback" generates spurious DOM elements and so on, but that can be fixed. 






2014-08-12 23:42 GMT+02:00 Wojtek Narczyński <woj... <at> power.com.pl>:
On 12.08.2014 23:27, Alberto G. Corona wrote:
Well, it is not a hack. It is the way hplayground works . normally it rewrite the HTML DOM of the implicit divs that are below  the event source. "at" permits to assign freely that location.

Okay, I see.

3. Are you yourself aware of any serious limitations of your approach?

--
Wojtek



--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Alberto G. Corona | 13 Aug 11:54 2014
Picon

Re: The Good, the Bad and the GUI

2014-08-13 11:05 GMT+02:00 Rik van der Kleij <rikvdkleij <at> gmail.com>:
Maybe you should port hplayground to purescript and virtual-dom :-)

why? for some special reason? 

On Wednesday, 13 August 2014 00:13:42 UTC+2, Alberto G. Corona wrote:
I did the todo application, (see todomvc.com) to check if the concept was expressive and robust enough to do it:


 I think that the model works and the haste compiler works very well too. I don´t know any serious limitation.  "wcallback" generates spurious DOM elements and so on, but that can be fixed. 






2014-08-12 23:42 GMT+02:00 Wojtek Narczyński <woj... <at> power.com.pl>:

On 12.08.2014 23:27, Alberto G. Corona wrote:
Well, it is not a hack. It is the way hplayground works . normally it rewrite the HTML DOM of the implicit divs that are below  the event source. "at" permits to assign freely that location.

Okay, I see.

3. Are you yourself aware of any serious limitations of your approach?

--
Wojtek



--
Alberto.



--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Rik van der Kleij | 13 Aug 12:34 2014
Picon

Re: The Good, the Bad and the GUI

Because it looks like virtual-dom is very well suited for how hplayground works. It's very efficient in rerendering the DOM tree when you have local changes. It's also very fast, see
http://elm-lang.org/blog/Blazing-Fast-Html.elm

Purescipt because it has a lot of speed in development (libraries) and generates in general leaner javascript. But I have no particular objections against Haste :-)

On Wednesday, 13 August 2014 11:55:04 UTC+2, Alberto G. Corona wrote:
2014-08-13 11:05 GMT+02:00 Rik van der Kleij <rikvd... <at> gmail.com>:
Maybe you should port hplayground to purescript and virtual-dom :-)

why? for some special reason? 

On Wednesday, 13 August 2014 00:13:42 UTC+2, Alberto G. Corona wrote:
I did the todo application, (see todomvc.com) to check if the concept was expressive and robust enough to do it:


 I think that the model works and the haste compiler works very well too. I don´t know any serious limitation.  "wcallback" generates spurious DOM elements and so on, but that can be fixed. 






2014-08-12 23:42 GMT+02:00 Wojtek Narczyński <woj... <at> power.com.pl>:

On 12.08.2014 23:27, Alberto G. Corona wrote:
Well, it is not a hack. It is the way hplayground works . normally it rewrite the HTML DOM of the implicit divs that are below  the event source. "at" permits to assign freely that location.

Okay, I see.

3. Are you yourself aware of any serious limitations of your approach?

--
Wojtek



--
Alberto.



--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Alberto G. Corona | 13 Aug 13:01 2014
Picon

Re: The Good, the Bad and the GUI

Yep, but virtual-dom is more appropriate for declarative reactive frameworks like elm. It need to know what parts of the DOM must be refreshed because the whole elm expression is reevaluated when an event happens. It need to detect the changes. Otherwise, it would have to repaint the whole screen in each event.

Declarative reactive is like a giant event handler that all the events execute. It may have some event/signal preprocessing  to mix events/signals depending on timings by means of some special combinators, but at the end it executes the whole declarative expression, which includes the re-generation  of all the rendering.

hplayground execute just the part of the monad corresponding to the branch in which the event happened. So it does not need to maintain the old and the new version of the DOM in order to detect the parts to be updated. It updates the affected branch of the DOM directly. So it must be faster (I did not check it however).


2014-08-13 12:34 GMT+02:00 Rik van der Kleij <rikvdkleij <at> gmail.com>:
Because it looks like virtual-dom is very well suited for how hplayground works. It's very efficient in rerendering the DOM tree when you have local changes. It's also very fast, see

Purescipt because it has a lot of speed in development (libraries) and generates in general leaner javascript. But I have no particular objections against Haste :-)

On Wednesday, 13 August 2014 11:55:04 UTC+2, Alberto G. Corona wrote:
2014-08-13 11:05 GMT+02:00 Rik van der Kleij <rikvd... <at> gmail.com>:

Maybe you should port hplayground to purescript and virtual-dom :-)

why? for some special reason? 

On Wednesday, 13 August 2014 00:13:42 UTC+2, Alberto G. Corona wrote:
I did the todo application, (see todomvc.com) to check if the concept was expressive and robust enough to do it:


 I think that the model works and the haste compiler works very well too. I don´t know any serious limitation.  "wcallback" generates spurious DOM elements and so on, but that can be fixed. 






2014-08-12 23:42 GMT+02:00 Wojtek Narczyński <woj... <at> power.com.pl>:

On 12.08.2014 23:27, Alberto G. Corona wrote:
Well, it is not a hack. It is the way hplayground works . normally it rewrite the HTML DOM of the implicit divs that are below  the event source. "at" permits to assign freely that location.

Okay, I see.

3. Are you yourself aware of any serious limitations of your approach?

--
Wojtek



--
Alberto.



--
Alberto.



--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 12 Aug 10:31 2014
Picon

Re: The Good, the Bad and the GUI

On 12.08.2014 01:14, Alberto G. Corona wrote:
> Wojtek. What you say is exactly what has been solved time ago by 
> fomlets in Web interfaces.  There are many formlet library and almost 
> all haskell web framework use formlets.
>
AFAIK, formlets at the server are very much like PHP, only with neater 
syntax, strong typing, and the like. Formlets tutorials teach you to put 
all your validation into the GUI, you really can't do much worse.

But, Alberto, your client side formlets look very interesting. I printed 
your Monad.Reader paper, and I'm definitely going to explore your ideas.

--

-- 
Kind regards,
Wojtek Narczyński
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Alberto G. Corona | 12 Aug 12:05 2014
Picon

Re: The Good, the Bad and the GUI




2014-08-12 10:31 GMT+02:00 Wojtek Narczyński <wojtek <at> power.com.pl>:
On 12.08.2014 01:14, Alberto G. Corona wrote:
Wojtek. What you say is exactly what has been solved time ago by fomlets in Web interfaces.  There are many formlet library and almost all haskell web framework use formlets.

AFAIK, formlets at the server are very much like PHP, only with neater syntax, strong typing, and the like. Formlets tutorials teach you to put all your validation into the GUI, you really can't do much worse.

I think that this horizontal separating the GUI from his application logic is a wrong conception of separation of concern.. as strange as it may sound, since that makes applications and components non composable. The MVC model is non composable!

A better separation of concern, for many purposes, is the vertical one in which each functionality include its own interface, logic and data model. The obstacle for implementing this kind of separation of concern is mainly technological, because each of the three layes uses different languages, so an horizontal separation is easier. But it is not appropriate for most purposes. It is very bad for creating GUIs!!




 

But, Alberto, your client side formlets look very interesting. I printed your Monad.Reader paper, and I'm definitely going to explore your ideas.
 
Thanks! 


--
Kind regards,
Wojtek Narczyński



--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Tikhon Jelvis | 12 Aug 01:21 2014
Picon

Re: The Good, the Bad and the GUI

For the original question: take a look at functional reactive programming (FRP). It takes a slightly different approach to the whole GUI problem, but, I've found, obviates some of your issues.

You can quickly play around with FRP and HTML UIs by using threepenny-gui and Reactive Banana. The former is a simple UI framework that lets you create and interact with HTML in Haskell, and the latter in a nice library for FRP. They work well together:

http://apfelmus.nfshost.com/blog/2013/08/02-reactive-banana-threepenny.html

There's a nice tutorial about FRP and Reactive Banana you can read on the Haskell Wiki. I haven't had the chance to go through it myself, but it looks promising.

http://www.haskell.org/haskellwiki/FRP_explanation_using_reactive-banana

If you're wondering about Haskell and UIs, I think FRP is the best place to look—it provides the most pleasant semantics for programming UIs that I've come across, although most of the libraries are still a bit experimental. (Implementing the exact semantics we'd like turned out to be very difficult!)

> The reactive solutions complicates the problem rather than to simplify it. That means that they are not the correct paradigm.

That's a very hasty, superficial way to dismiss a whole paradigm!

FRP libraries have proven *difficult to implement*, but this does not mean they somehow "complicate the problem". The real insight with FRP is developing a nice semantics *for the end user* and making it simpler to work with the libraries, at the expense of a more complex implementation. It's a parallel to functional programming at large: we're willing to trade complexity in GHC in return for a nicer high-level programming environment.

Formlets are an interesting concept, but they seem to be significantly more narrow than FRP. How do formlets address continuous things like animations or mouse movement?

Also, a lot of the examples (at least on the Haskell wiki[1]) seem pretty amenable to FRP. How is
 
    chooseBool :: Form Bool
    chooseBool = enumRadio [(True, "Yes"), (False, "No")] True

significantly different from just providing a Behavior Bool in the spirit of FRP?


On Mon, Aug 11, 2014 at 3:57 PM, Wojtek Narczyński <wojtek <at> power.com.pl> wrote:

On 12.08.2014 00:53, Alberto G. Corona wrote:
I think that the GUI people hace to embrace the formlet concept, used in HTML interfaces sooner better than later. The GUI development has lost the train by trying to interface C libraries that are decades old. The reactive solutions complicates the problem rather than to simplify it. That means that they are not the correct paradigm.

I'm mainly interested in HTML/JS GUIs. Perhaps I should have stated it explicitly upfront.

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Alberto G. Corona | 12 Aug 11:40 2014
Picon

Re: The Good, the Bad and the GUI




2014-08-12 1:21 GMT+02:00 Tikhon Jelvis <tikhon <at> jelv.is>:
For the original question: take a look at functional reactive programming (FRP). It takes a slightly different approach to the whole GUI problem, but, I've found, obviates some of your issues.

You can quickly play around with FRP and HTML UIs by using threepenny-gui and Reactive Banana. The former is a simple UI framework that lets you create and interact with HTML in Haskell, and the latter in a nice library for FRP. They work well together:

http://apfelmus.nfshost.com/blog/2013/08/02-reactive-banana-threepenny.html

There's a nice tutorial about FRP and Reactive Banana you can read on the Haskell Wiki. I haven't had the chance to go through it myself, but it looks promising.

http://www.haskell.org/haskellwiki/FRP_explanation_using_reactive-banana

If you're wondering about Haskell and UIs, I think FRP is the best place to look—it provides the most pleasant semantics for programming UIs that I've come across, although most of the libraries are still a bit experimental. (Implementing the exact semantics we'd like turned out to be very difficult!)

> The reactive solutions complicates the problem rather than to simplify it. That means that they are not the correct paradigm.

That's a very hasty, superficial way to dismiss a whole paradigm!

Yes!

 I was just trying to be a bit provoking. Sorry.

The objections about the use of  current FRP models for GUIs are here:


and here:


Allthough FRP is too wide. Monadic FRP is more appropriate for GUIs for the same reasons.  hplayground uses monadic FRP + formlets


FRP libraries have proven *difficult to implement*, but this does not mean they somehow "complicate the problem". The real insight with FRP is developing a nice semantics *for the end user* and making it simpler to work with the libraries, at the expense of a more complex implementation. It's a parallel to functional programming at large: we're willing to trade complexity in GHC in return for a nicer high-level programming environment.

Formlets are an interesting concept, but they seem to be significantly more narrow than FRP. How do formlets address continuous things like animations or mouse movement?

Also, a lot of the examples (at least on the Haskell wiki[1]) seem pretty amenable to FRP. How is
 
    chooseBool :: Form Bool
    chooseBool = enumRadio [(True, "Yes"), (False, "No")] True

significantly different from just providing a Behavior Bool in the spirit of FRP?


On Mon, Aug 11, 2014 at 3:57 PM, Wojtek Narczyński <wojtek <at> power.com.pl> wrote:

On 12.08.2014 00:53, Alberto G. Corona wrote:
I think that the GUI people hace to embrace the formlet concept, used in HTML interfaces sooner better than later. The GUI development has lost the train by trying to interface C libraries that are decades old. The reactive solutions complicates the problem rather than to simplify it. That means that they are not the correct paradigm.

I'm mainly interested in HTML/JS GUIs. Perhaps I should have stated it explicitly upfront.

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe




--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 12 Aug 13:03 2014
Picon

Re: The Good, the Bad and the GUI

On 12.08.2014 11:40, Alberto G. Corona wrote:

> The reactive solutions complicates the problem rather than to simplify it. That means that they are not the correct paradigm.

That's a very hasty, superficial way to dismiss a whole paradigm!

Yes!

I was just trying to be a bit provoking. Sorry.


I would really like to see a complex web form (think Facebook, VAT Invoice, Tax forms) done in FRP. The harsh reality is that FRP for GUIs still has to prove that its utility reaches beyond the game of Pong.

--
Wojtek
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Heinrich Apfelmus | 12 Aug 23:50 2014
Picon

Re: The Good, the Bad and the GUI

Wojtek Narczyński wrote:
> I would really like to see a complex web form (think Facebook, VAT 
> Invoice, Tax forms) done in FRP. The harsh reality is that FRP for GUIs 
> still has to prove that its utility reaches beyond the game of Pong.

Like this?

   http://www.haskell.org/haskellwiki/Reactive-banana/Examples#crud

It's still a toy model, but I think it captures the essential 
difficulties. A full blown tax form would just be more of the same.

Best regards,
Heinrich Apfelmus

--
http://apfelmus.nfshost.com

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 13 Aug 00:33 2014
Picon

Re: The Good, the Bad and the GUI

On 12.08.2014 23:50, Heinrich Apfelmus wrote:
> Wojtek Narczyński wrote:
>> I would really like to see a complex web form (think Facebook, VAT 
>> Invoice, Tax forms) done in FRP. The harsh reality is that FRP for 
>> GUIs still has to prove that its utility reaches beyond the game of 
>> Pong.
>
> Like this?
>
>   http://www.haskell.org/haskellwiki/Reactive-banana/Examples#crud
>
> It's still a toy model, but I think it captures the essential 
> difficulties. A full blown tax form would just be more of the same.
>
>
Is it live anywhere? I'd like to test it for HTML injection. The #1 
difficulty is validation. Is there any in this example? I can't see any. 
This really does not qualify as a complex web form.

You'll get _exponentially_ more of the same. See paper "Plato: A 
Compiler for Interactive Web Forms", 
http://www.cs.uic.edu/~hinrichs/papers/hinrichs2011plato.pdf

--

-- 
Wojtek
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Heinrich Apfelmus | 13 Aug 15:42 2014
Picon

Re: The Good, the Bad and the GUI

Wojtek Narczyński wrote:
> Heinrich Apfelmus wrote:
>> Wojtek Narczyński wrote:
>>>
>>> I would really like to see a complex web form (think Facebook, VAT 
>>> Invoice, Tax forms) done in FRP. The harsh reality is that FRP for 
>>> GUIs still has to prove that its utility reaches beyond the game of 
>>> Pong.
>>
>> Like this?
>>
>>   http://www.haskell.org/haskellwiki/Reactive-banana/Examples#crud
>>
>> It's still a toy model, but I think it captures the essential 
>> difficulties. A full blown tax form would just be more of the same.
>>
>>
> Is it live anywhere? I'd like to test it for HTML injection.

It's actually a wxHaskell applications, the screenshot is from a
temporary but now deprecated adaption to Threepenny-gui. So, the issue
of HTML injection does not arise. (It would not arise in a HTML context
either, because of strong typing.)

The key point about this CRUD example, which is not shown in the
screenshot, is that it has immediate feedback: values in the list box
change as you type. Editing the name on the right-hand side will change
the name in the list box, and changing the filter will immediately
update the available names in the list box.

> The #1 
> difficulty is validation. Is there any in this example? I can't see any. 
> This really does not qualify as a complex web form.
>
> You'll get _exponentially_ more of the same. See paper "Plato: A 
> Compiler for Interactive Web Forms", 
> http://www.cs.uic.edu/~hinrichs/papers/hinrichs2011plato.pdf

Validation is mainly a question of *how* to present feedback about
invalid data to the user -- for instance by making invalid data
impossible to enter, or by showing errors in red and retaining the last 
correct value, etc.

I would consider this as a narrow part of GUI programming. For me, GUI 
programming is about user interfaces and interaction design in general, 
including zoom, animation, games, and so on. FRP is a better tool at 
this than the traditional event-based style.

Of course, in the context of form validation, FRP would be a building 
block: It does not give any advice on which feedback to present to the 
user, but it does allow you to quickly implement whatever feedback you 
have chosen to present.

Still, even for the more narrow problem of forms and input validation, I 
don't see how you arrive at your claim that "Haskell is however not 
great for GUIs". This seems like a problem that can be solved with a 
traditional DSL approach, and I would be surprised if Haskell were 
unsuitable as a host language, contrary to what your claim seems to 
imply. Whether DSLs along these lines are already available is another 
question. Alberto mentioned one, another one would be [1].

  [1]: http://www.sandr.dds.nl/publications/FForms.pdf

Best regards,
Heinrich Apfelmus

--
http://apfelmus.nfshost.com

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 13 Aug 23:19 2014
Picon

Re: The Good, the Bad and the GUI

On 13.08.2014 15:42, Heinrich Apfelmus wrote:
> Validation is mainly a question of *how* to present feedback about
> invalid data to the user -- for instance by making invalid data
> impossible to enter, or by showing errors in red and retaining the 
> last correct value, etc.

I don't even know how to capture validation rules in such a way that 
they were easy to use from the GUI layer. I suspect if they were 
captured well, whatever well might mean in this context, a functioning 
GUI could be autogenerated from those rules.

And I don't understand FRP code. I could however understand Eduardo's 
client side formlets almost immediately. Not now they work below, how to 
use them.

> Still, even for the more narrow problem of forms and input validation, 
> I don't see how you arrive at your claim that "Haskell is however not 
> great for GUIs". This seems like a problem that can be solved with a 
> traditional DSL approach, and I would be surprised if Haskell were 
> unsuitable as a host language, contrary to what your claim seems to 
> imply. Whether DSLs along these lines are already available is another 
> question. Alberto mentioned one, another one would be [1].
>

Oh, please. Haskell is great for parsing, because you can build a parser 
with e.g. parsec, attoparsec, uuparse, trifeca, in no time. Even I can 
do it. Haskell is great for concurrency, because it has lightweight 
threads, STM, and a fabulous book about it. Haskell is great for GUIs, 
because.... how about you finish this statement, I don't know how to.

--

-- 
Kind reagrds,
Wojtek Narczynski
Alexander Vieth | 13 Aug 23:28 2014

Re: The Good, the Bad and the GUI

> Oh, please. Haskell is great for parsing, because you can build a parser with e.g. parsec, attoparsec,
uuparse, trifeca, in no time. Even I can do it. Haskell is great for concurrency, because it has
lightweight threads, STM, and a fabulous book about it. Haskell is great for GUIs, because.... how about
you finish this statement, I don't know how to.

Before parsec, attoparsec, uuparse, et al were invented, was Haskell no good for parsing? When we speak of
Haskell do we speak of the entire ecosystem, or just the language itself? I think Heinrich meant that
Haskell, the language, is probably capable of carrying a great library for expressing GUI's, even if we
haven't yet seen it implemented.

Alex

On 2014-08-13, at 5:19 PM, Wojtek Narczyński wrote:

> On 13.08.2014 15:42, Heinrich Apfelmus wrote:
>> Validation is mainly a question of *how* to present feedback about
>> invalid data to the user -- for instance by making invalid data
>> impossible to enter, or by showing errors in red and retaining the last correct value, etc.
> 
> I don't even know how to capture validation rules in such a way that they were easy to use from the GUI layer. I
suspect if they were captured well, whatever well might mean in this context, a functioning GUI could be
autogenerated from those rules.
> 
> And I don't understand FRP code. I could however understand Eduardo's client side formlets almost
immediately. Not now they work below, how to use them.
> 
>> Still, even for the more narrow problem of forms and input validation, I don't see how you arrive at your
claim that "Haskell is however not great for GUIs". This seems like a problem that can be solved with a
traditional DSL approach, and I would be surprised if Haskell were unsuitable as a host language,
contrary to what your claim seems to imply. Whether DSLs along these lines are already available is
another question. Alberto mentioned one, another one would be [1].
>> 
> 
> Oh, please. Haskell is great for parsing, because you can build a parser with e.g. parsec, attoparsec,
uuparse, trifeca, in no time. Even I can do it. Haskell is great for concurrency, because it has
lightweight threads, STM, and a fabulous book about it. Haskell is great for GUIs, because.... how about
you finish this statement, I don't know how to.
> 
> -- 
> Kind reagrds,
> Wojtek Narczynski
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe <at> haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 14 Aug 01:19 2014
Picon

Re: The Good, the Bad and the GUI

On 13.08.2014 23:28, Alexander Vieth wrote:
>> Oh, please. Haskell is great for parsing, because you can build a parser with e.g. parsec, attoparsec,
uuparse, trifeca, in no time. Even I can do it. Haskell is great for concurrency, because it has
lightweight threads, STM, and a fabulous book about it. Haskell is great for GUIs, because.... how about
you finish this statement, I don't know how to.
> Before parsec, attoparsec, uuparse, et al were invented, was Haskell no good for parsing? When we speak of
Haskell do we speak of the entire ecosystem, or just the language itself?

It is clear what I meant.

> I think Heinrich meant that Haskell, the language, is probably capable of carrying a great library for
expressing GUI's, even if we haven't yet seen it implemented.
>
>

Haskell, the language, is great for GUIs, because... "(it) is probably 
capable of carrying a great library for expressing GUI's, even if we 
haven't yet seen it implemented." This is too much, I need to sleep it off.
Tom Ellis | 14 Aug 01:23 2014
Picon

Re: The Good, the Bad and the GUI

On Thu, Aug 14, 2014 at 01:19:19AM +0200, Wojtek Narczyński wrote:
> On 13.08.2014 23:28, Alexander Vieth wrote:
> >>Oh, please. Haskell is great for parsing, because you can build a parser
> >> with e.g.  parsec, attoparsec, uuparse, trifeca, in no time.  Even I
> >> can do it.  Haskell is great for concurrency, because it has
> >> lightweight threads, STM, and a fabulous book about it.  Haskell is
> >> great for GUIs, because....  how about you finish this statement, I
> >> don't know how to.
>
> >Before parsec, attoparsec, uuparse, et al were invented, was Haskell no
> > good for parsing?  When we speak of Haskell do we speak of the entire
> > ecosystem, or just the language itself?
> 
> It is clear what I meant.
> 
> >I think Heinrich meant that Haskell, the language, is probably capable of
> > carrying a great library for expressing GUI's, even if we haven't yet
> > seen it implemented.
> 
> Haskell, the language, is great for GUIs, because... "(it) is
> probably capable of carrying a great library for expressing GUI's,
> even if we haven't yet seen it implemented." This is too much, I
> need to sleep it off.

Perhaps you could give an example of a language that is "great for GUIs" and
a great functional snippet of GUI code in that language.  Otherwise we're
just discussing in the abstract which tends not to be very helpful.

Tom
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Heinrich Apfelmus | 15 Aug 13:27 2014
Picon

Re: The Good, the Bad and the GUI

Wojtek Narczyński wrote:
> Alexander Vieth wrote:
> 
>> I think Heinrich meant that Haskell, the language, is probably capable 
>> of carrying a great library for expressing GUI's, even if we haven't 
>> yet seen it implemented.
> 
> Haskell, the language, is great for GUIs, because... "(it) is probably 
> capable of carrying a great library for expressing GUI's, even if we 
> haven't yet seen it implemented." This is too much, I need to sleep it off.

That's indeed what I wanted to say, Alexander.

Wojtek, precise wording is important to us. We make no claim that 
"Haskell is great for GUIs", only that it is probably capable of 
carrying a great library for expressing GUIs. This distinction is 
important because it gives advice on how to solve the problem -- is 
there some inherent defect in the language and its semantics that makes 
it difficult, or is the problem more on of manpower?

Similar for the term "GUI". Apparently, you are interested in a narrow 
aspect of GUI programming -- input forms and validation. Which is 
totally fine, but not nearly as broad as GUI programming in general. The 
latter benefits immensely from FRP, but FRP is orthogonal to the 
question of validation.

Best regards,
Heinrich Apfelmus

--
http://apfelmus.nfshost.com

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 16 Aug 23:51 2014
Picon

Re: The Good, the Bad and the GUI

On 15.08.2014 13:27, Heinrich Apfelmus wrote:
> Wojtek, precise wording is important to us. We make no claim that 
> "Haskell is great for GUIs", only that it is probably capable of 
> carrying a great library for expressing GUIs. This distinction is 
> important because it gives advice on how to solve the problem -- is 
> there some inherent defect in the language and its semantics that 
> makes it difficult, or is the problem more on of manpower?
>
GUIs are hard, in any language.
-----------------------------------------------------------
http://www.emarcus.org/papers/gpce2009-marcus.pdf
http://www.cs.uic.edu/~hinrichs/papers/hinrichs2011plato.pdf

I am looking for solutions on a Haskell list, because I think chances of 
finding them here are higher than elsewhere.

So let me ask again, any ideas on how would you write down rules for: 
text field lengths or numeric field ranges, in such a library, for a start?

> Similar for the term "GUI". Apparently, you are interested in a narrow 
> aspect of GUI programming -- input forms and validation. Which is 
> totally fine, but not nearly as broad as GUI programming in general.
>
You are totally right here. I should have said I meant Web UIs, mostly 
interactive forms.

--

-- 
Wojtek
ok | 12 Aug 05:31 2014
Picon

Re: The Good, the Bad and the GUI

> If you declare Person class
> in Java, you automatically get a thingy that you can readily use in UI
> construction, because all the fields can temporarily be null, even the
> required ones. In Haskell you'd need two data types: the usual proper
> Haskell data type, and another which wraps every field in Maybe,
> facilitates editing, validation, etc. Perhaps it would be possible to
> generate one data type from the other, or generate both from a common
> specification.

You seem to be referring to the "incompletely initialised object"
anti-pattern.  The books I have about concurrency in Java/on the JVM
strongly recommend making Java objects immutable when you can.

Even in Visual Basic, if an object is "constructed" via a lengthy
sequence of steps, it is good design to distinguish between two
different things": a fully constructed Foo object and a FooBuilder
object.  Sometimes they need to be the same object, but there really
do need to be two *interfaces*.  Once past the construction phase,
you want to KNOW that the object is fully constructed, and there are
things the constructor might do that you DON'T want other objects to
do.

Reflecting on the use case you are talking about, it seems to be
that there are two conceptually very distinct objects here.
There is a FooForm object which is intimately connected to the
user interface and may only partially describe a Foo, and there
is a Foo object which is *not* connected to the user interface
or if it is, is connected in a quite different way, exposing
quite different behaviours.  Reflecting further, suppose I fill
out a form and press a button to commit this object, then I
edit the form to be a little different, and press the button
again.  Creating a new *object* by revising a single *form* is
clearly distinct from *editing* an existing object.

What I think about this, therefore, is that you want a clear
distinction between FooForms and Foos (at the very minimum a
distinction between FooForm and Foo interfaces) no matter WHAT
kind of programming language you are using, and I don't see
Haskell as anything special here.

> Let me write the same thing in other words. It is not controversial to
> say on this list that specifying what is correct means, is a good idea.
> But for GUIs, in addition to the strong type, you need another relaxed
> type to hold the values temporarily, until the human manages to deliver
> correct data, often by trial and error.

In short, we agree, that is indeed *ANOTHER* type.

Not only may a FooForm not yet hold information a Foo needs,
a FooForm may hold information that a Foo does *not* need.
For example, a FooForm might need to hold on to some credentials
to prove that it is authorised to create Foo objects, whereas a
Foo object might not.

In Smalltalk, Java, C#, &c one might look at ways of automatically
constructing FooForms from Foo classes + annotations.  Using some
sort of generic processing, one could also do this in Haskell.
Having two classes/types does not have to be twice as much work.
Wojtek Narczyński | 12 Aug 09:55 2014
Picon

Re: The Good, the Bad and the GUI

On 12.08.2014 05:31, ok <at> cs.otago.ac.nz wrote:
>> If you declare Person class
>> in Java, you automatically get a thingy that you can readily use in UI
>> construction, because all the fields can temporarily be null, even the
>> required ones. In Haskell you'd need two data types: the usual proper
>> Haskell data type, and another which wraps every field in Maybe,
>> facilitates editing, validation, etc. Perhaps it would be possible to
>> generate one data type from the other, or generate both from a common
>> specification.
> You seem to be referring to the "incompletely initialised object"
> anti-pattern.  The books I have about concurrency in Java/on the JVM
> strongly recommend making Java objects immutable when you can.
>
> Even in Visual Basic, if an object is "constructed" via a lengthy
> sequence of steps, it is good design to distinguish between two
> different things": a fully constructed Foo object and a FooBuilder
> object.  Sometimes they need to be the same object, but there really
> do need to be two *interfaces*.  Once past the construction phase,
> you want to KNOW that the object is fully constructed, and there are
> things the constructor might do that you DON'T want other objects to
> do.

Take a VAT Invoice as an example. You will have:

Invoice, InvoiceBuilder,
InvoiceLineItem, InvoiceLineItemBuilder,
InvoiceCustomer, InvoiceCustomerBuilder,
InvoiceSummary, (no Builder, as this is calculated)
(many, many more classes in a realistic system)

Now, where the rather complex validation belongs? Optional / mandatory 
requirements, lengths, ranges, regexps, control sums, field 
interdependencies, autocompletes, server sent notifications? Where to 
put all of this? To regular classes, to builder classes, or to both?

--

-- 
Wojtek
Jim Stuttard | 12 Aug 10:28 2014
Picon

Re: The Good, the Bad and the GUI


On 08/12/2014 08:55 AM, Wojtek Narczyński wrote:
> On 12.08.2014 05:31, ok <at> cs.otago.ac.nz wrote:
>>> If you declare Person class
>>> in Java, you automatically get a thingy that you can readily use in UI
>>> construction, because all the fields can temporarily be null, even the
>>> required ones. In Haskell you'd need two data types: the usual proper
>>> Haskell data type, and another which wraps every field in Maybe,
>>> facilitates editing, validation, etc. Perhaps it would be possible to
>>> generate one data type from the other, or generate both from a common
>>> specification.
>> You seem to be referring to the "incompletely initialised object"
>> anti-pattern. The books I have about concurrency in Java/on the JVM
>> strongly recommend making Java objects immutable when you can.
>>
>> Even in Visual Basic, if an object is "constructed" via a lengthy
>> sequence of steps, it is good design to distinguish between two
>> different things": a fully constructed Foo object and a FooBuilder
>> object. Sometimes they need to be the same object, but there really
>> do need to be two *interfaces*. Once past the construction phase,
>> you want to KNOW that the object is fully constructed, and there are
>> things the constructor might do that you DON'T want other objects to
>> do.
>
> Take a VAT Invoice as an example. You will have:
>
> Invoice, InvoiceBuilder,
> InvoiceLineItem, InvoiceLineItemBuilder,
> InvoiceCustomer, InvoiceCustomerBuilder,
> InvoiceSummary, (no Builder, as this is calculated)
> (many, many more classes in a realistic system)
>
> Now, where the rather complex validation belongs? Optional / mandatory 
> requirements, lengths, ranges, regexps, control sums, field 
> interdependencies, autocompletes, server sent notifications? Where to 
> put all of this? To regular classes, to builder classes, or to both?
These sound like cross-cutting concerns. I found this paper on monads 
and mixins for AOP.

http://i.cs.hku.hk/~bruno/papers/MixinAspects.pdf

hth

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Chris Warburton | 12 Aug 11:30 2014

Re: The Good, the Bad and the GUI

Wojtek Narczyński <wojtek <at> power.com.pl> writes:

> Take a VAT Invoice as an example. You will have:
>
> Invoice, InvoiceBuilder,
> InvoiceLineItem, InvoiceLineItemBuilder,
> InvoiceCustomer, InvoiceCustomerBuilder,
> InvoiceSummary, (no Builder, as this is calculated)
> (many, many more classes in a realistic system)
>
> Now, where the rather complex validation belongs? Optional / mandatory
> requirements, lengths, ranges, regexps, control sums, field
> interdependencies, autocompletes, server sent notifications? Where to
> put all of this? To regular classes, to builder classes, or to both?

The current trend in OOP Web frameworks Model-View-Controller.

In MVP, Invoice/InvoiceLineItem/InvoiceCustomer/InvoiceSummary/etc. are
the Model: they should form a standalone 'simulation' of an Invoice,
without concerning themselves with 'external' aspects.

Validation, bootstrapping (builders), etc. live in the Controller
layer.

If the server notifications are informing the user about the behaviour
of the Model, they're part of the View. If they facilitate interaction
they're part of the Controller.

There are many functional styles which suit Models:
 - The pseudo-imperative style of Applicative/Monad/Arrow/etc.
 - The 'interacting streams' style, eg. infinite [(Request, Response)]
   lists.
 - Functional Reactive Programming

Since Controllers can't mutate Models in Haskell, they must do one of
two things:
 - Influence some 'future' behaviour of the Model, eg. using FRP
 - Build a new Model from the given settings

To me the latter choice looks similar to a parsing problem. You say that
Haskell's "great" at parsing, which I think contradicts your statement
that "in Haskell it is unusual to deal with data that is incomplete or
otherwise erroneous".

In Haskell we deal with incomplete data all the time using lazy
evaluation. Erroneous data doesn't require Maybes all over our data: it
just needs one big Maybe in the 'parsing' function; or, more likely,
"Either [Error]" detailing the problems which were found.

Views are straightforward: recurse over the data, use FRP, etc.

Cheers,
Chris
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 12 Aug 12:46 2014
Picon

Re: The Good, the Bad and the GUI

W dniu 2014-08-12 11:30, Chris Warburton pisze:
> Wojtek Narczyński<wojtek <at> power.com.pl>  writes:
>
>> ut all of this? To regular classes, to builder classes, or to both?
> The current trend in OOP Web frameworks Model-View-Controller.
We've been doing this for 15 years, and believe me, it works only so-so.
> To me the latter choice looks similar to a parsing problem. You say that
> Haskell's "great" at parsing, which I think contradicts your statement
> that "in Haskell it is unusual to deal with data that is incomplete or
> otherwise erroneous".
Grammars have been tried for GUIs, without any success. I'm not aware of 
any even moderate size GUI constructed this way.
> In Haskell we deal with incomplete data all the time using lazy
> evaluation. Erroneous data doesn't require Maybes all over our data: it
> just needs one big Maybe in the 'parsing' function; or, more likely,
> "Either [Error]" detailing the problems which were found.
>
Continuing my VAT Invoice example, let us say a LineItem that does not 
have a product description (missing value), but it does have all the 
numeric fields filled in.  It is partly erroneous, but it can be 
included in calculation of the total. How would you handle it with 
Either [Error] Invoice style code?

--
Cheers,
Wojtek Narczyński
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Alberto G. Corona | 12 Aug 12:54 2014
Picon

Re: The Good, the Bad and the GUI




2014-08-12 12:46 GMT+02:00 Wojtek Narczyński <wojtek <at> power.com.pl>:
W dniu 2014-08-12 11:30, Chris Warburton pisze:
Wojtek Narczyński<wojtek <at> power.com.pl>  writes:


ut all of this? To regular classes, to builder classes, or to both?
The current trend in OOP Web frameworks Model-View-Controller.
We've been doing this for 15 years, and believe me, it works only so-so.

To me the latter choice looks similar to a parsing problem. You say that
Haskell's "great" at parsing, which I think contradicts your statement
that "in Haskell it is unusual to deal with data that is incomplete or
otherwise erroneous".
Grammars have been tried for GUIs, without any success. I'm not aware of any even moderate size GUI constructed this way.

Well, a formlet is essentially an applicative parser of HTTP parameters + a writer of HTML code. it works pretty well. and it can create the complete logic of a page, not only the interface  if we add a monadic instance.
 
In Haskell we deal with incomplete data all the time using lazy
evaluation. Erroneous data doesn't require Maybes all over our data: it
just needs one big Maybe in the 'parsing' function; or, more likely,
"Either [Error]" detailing the problems which were found.

Continuing my VAT Invoice example, let us say a LineItem that does not have a product description (missing value), but it does have all the numeric fields filled in.  It is partly erroneous, but it can be included in calculation of the total. How would you handle it with Either [Error] Invoice style code?

--
Cheers,
Wojtek Narczyński

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Tom Ellis | 13 Aug 12:37 2014
Picon

Re: The Good, the Bad and the GUI

On Tue, Aug 12, 2014 at 12:46:05PM +0200, Wojtek Narczyński wrote:
> Continuing my VAT Invoice example, let us say a LineItem that does
> not have a product description (missing value), but it does have all
> the numeric fields filled in.  It is partly erroneous, but it can be
> included in calculation of the total. How would you handle it with
> Either [Error] Invoice style code?

What sort of functionality are you looking for exactly?  What's your
objection to (for example)

    data LineItemGeneral a = LineItem { price :: Price
                                      , quantity :: Quantity
                                      , description :: a }

    type LineItem = LineItemGeneral String
    type LineItemPossiblyIncomplete = LineItemGeneral (Maybe String)
    type LineItemWithoutDescription = LineItemGeneral ()

    totalValue :: LineItemGeneral a -> Value
    totalValue lineItem = price lineItem * quantity lineItem

`totalValue` works for all sorts of line items, whether they have a
description or not.

Tom
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 13 Aug 22:31 2014
Picon

Re: The Good, the Bad and the GUI


On 13.08.2014 12:37, Tom Ellis wrote:
> On Tue, Aug 12, 2014 at 12:46:05PM +0200, Wojtek Narczyński wrote:
>> Continuing my VAT Invoice example, let us say a LineItem that does
>> not have a product description (missing value), but it does have all
>> the numeric fields filled in.  It is partly erroneous, but it can be
>> included in calculation of the total. How would you handle it with
>> Either [Error] Invoice style code?
> What sort of functionality are you looking for exactly?  What's your
> objection to (for example)
>
>      data LineItemGeneral a = LineItem { price :: Price
>                                        , quantity :: Quantity
>                                        , description :: a }
>
>      type LineItem = LineItemGeneral String
>      type LineItemPossiblyIncomplete = LineItemGeneral (Maybe String)
>      type LineItemWithoutDescription = LineItemGeneral ()
>
>      totalValue :: LineItemGeneral a -> Value
>      totalValue lineItem = price lineItem * quantity lineItem
>
> `totalValue` works for all sorts of line items, whether they have a
> description or not.
>
>
Let's say the user entered:

No, Name, Qty, Price
--------------------------------------------
1. [        ]   [99] [10]
2. [Water] [    ] [10]
3. [Juice]   [  1] [    ]

The GUI should display total of 990, and signal four errors: three 
missing values (ideally different color of the input fields), and the 
whole invoice incomplete. The Either [Error] Invoice type does not work, 
because can either display the errors or calculate total from a correct 
invoice, never both. And you can't even create LineItem for 2. and 3. 
Well, maybe you can with laziness, but how would total work then?

That's why I asked in my original post, whether I'd need two types, one 
for correct complete invoice, and another for the invoice "in statu 
nascendi". And how to obtain them, lazily, and I mean the person, not 
the language.

--

-- 
Wojtek
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Steve Schafer | 13 Aug 22:49 2014

Re: The Good, the Bad and the GUI

On Wed, 13 Aug 2014 22:31:31 +0200, Wojtek Narczy?ski
<wojtek <at> power.com.pl> wrote:

>Let's say the user entered:
>
>No, Name, Qty, Price
>--------------------------------------------
>1. [        ]   [99] [10]
>2. [Water] [    ] [10]
>3. [Juice]   [  1] [    ]
>
>The GUI should display total of 990

Why? Why are any of these erroneous line items included in the total? I
would argue that an incomplete or otherwise erroneous line item is not
part of the invoice.

I don't know of any (reasonable) online merchant that requires the user
to separately enter item, quantity and price. Typically, the user
interface is designed explicitly to prohibit an incomplete line item of
this sort.

-Steve Schafer
Wojtek Narczyński | 13 Aug 23:27 2014
Picon

Re: The Good, the Bad and the GUI

On 13.08.2014 22:49, Steve Schafer wrote:
> On Wed, 13 Aug 2014 22:31:31 +0200, Wojtek Narczy?ski
> <wojtek <at> power.com.pl> wrote:
>
>> Let's say the user entered:
>>
>> No, Name, Qty, Price
>> --------------------------------------------
>> 1. [        ]   [99] [10]
>> 2. [Water] [    ] [10]
>> 3. [Juice]   [  1] [    ]
>>
>> The GUI should display total of 990
> Why? Why are any of these erroneous line items included in the total? I
> would argue that an incomplete or otherwise erroneous line item is not
> part of the invoice.
Say that the error is merely a warning, for example the user entered 'A' 
which is suspiciously short.
> I don't know of any (reasonable) online merchant that requires the user
> to separately enter item, quantity and price.
Yes, it is terrible. It's called "accounting".
Chris Warburton | 14 Aug 10:36 2014

Re: The Good, the Bad and the GUI

Wojtek Narczyński <wojtek <at> power.com.pl> writes:

> On 13.08.2014 22:49, Steve Schafer wrote:
>> Why? Why are any of these erroneous line items included in the total? I
>> would argue that an incomplete or otherwise erroneous line item is not
>> part of the invoice.
> Say that the error is merely a warning, for example the user entered
> A' which is suspiciously short.

The goalposts have moved again, although this time it's trivial:

checkForWarnings :: Invoice -> [Warning]

What counts as a warning, how they affect the workflow and how they're
presented are business decisions.

Cheers,
Chris
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Tom Ellis | 14 Aug 01:21 2014
Picon

Re: The Good, the Bad and the GUI

On Wed, Aug 13, 2014 at 10:31:31PM +0200, Wojtek Narczyński wrote:
> On 13.08.2014 12:37, Tom Ellis wrote:
> >On Tue, Aug 12, 2014 at 12:46:05PM +0200, Wojtek Narczyński wrote:
> >>Continuing my VAT Invoice example, let us say a LineItem that does
> >>not have a product description (missing value), but it does have all
> >>the numeric fields filled in.  It is partly erroneous, but it can be
> >>included in calculation of the total. How would you handle it with
> >>Either [Error] Invoice style code?
> >What sort of functionality are you looking for exactly?  What's your
> >objection to (for example)
> >
> >     data LineItemGeneral a = LineItem { price :: Price
> >                                       , quantity :: Quantity
> >                                       , description :: a }
> >
> >     type LineItem = LineItemGeneral String
> >     type LineItemPossiblyIncomplete = LineItemGeneral (Maybe String)
> >     type LineItemWithoutDescription = LineItemGeneral ()
> >
> >     totalValue :: LineItemGeneral a -> Value
> >     totalValue lineItem = price lineItem * quantity lineItem
> >
> >`totalValue` works for all sorts of line items, whether they have a
> >description or not.
>
> Let's say the user entered:
> 
> No, Name, Qty, Price
> --------------------------------------------
> 1. [        ]   [99] [10]
> 2. [Water] [    ] [10]
> 3. [Juice]   [  1] [    ]
> 
> The GUI should display total of 990, and signal four errors: three
> missing values (ideally different color of the input fields), and
> the whole invoice incomplete. The Either [Error] Invoice type does
> not work, because can either display the errors or calculate total
> from a correct invoice, never both. And you can't even create
> LineItem for 2. and 3. Well, maybe you can with laziness, but how
> would total work then?
> 
> That's why I asked in my original post, whether I'd need two types,
> one for correct complete invoice, and another for the invoice "in
> statu nascendi". And how to obtain them, lazily, and I mean the
> person, not the language.

Perhaps I don't grasp exactly what you're getting at, but this seems easy. 
Please let me know where my proposed solution fails to provide what you
need.  

I do see that you originally said "In Haskell you'd need two data types: the
usual proper Haskell data type, and another which wraps every field in
Maybe, facilitates editing, validation, etc.".  You don't actually *need*
the version without the Maybe, but you can provide it if you want some
additional type safety.  If you'd like to see an example of making that
nice and easy with minimal boilerplate please ask.

    import Control.Applicative
    import Data.Maybe
    import Control.Arrow

    type Quantity = Double
    type Price = Double
    type Value = Double

    data LineItem = LineItem { name :: Maybe String
                             , quantity :: Maybe Quantity
                             , price :: Maybe Price }

    data Field = NameField | QuantityField | PriceField
               deriving Show

    data Error = Error { item :: Int
                       , missing :: Field }
               deriving Show

    value :: LineItem -> Maybe Value
    value l = (*) <$> price l <*> quantity l

    totalValue :: [LineItem] -> Value
    totalValue = sum . map (fromMaybe 0 . value)

    missingFields :: LineItem -> [Field]
    missingFields l = n ++ q ++ p
      where n = if name l == Nothing then [NameField] else []
            q = if quantity l == Nothing then [QuantityField] else []
            p = if price l == Nothing then [PriceField] else []

    errors :: [LineItem] -> [Error]
    errors = concatMap (\(i, es) -> map (Error i) es)   
             . zip [1..]
             . map missingFields    

    guiResponse :: [LineItem] -> (Value, [Error])
    guiResponse = totalValue &&& errors

    exampleData :: [LineItem]
    exampleData = [ LineItem Nothing        (Just 99) (Just 10)
                  , LineItem (Just "Water") Nothing   (Just 10)
                  , LineItem (Just "Juice") (Just 1)  Nothing ]

    -- *Main> guiResponse exampleData 
    -- (990.0, [ Error {item = 1, missing = NameField}
    --         , Error {item = 2, missing = QuantityField}
    --         , Error {item = 3, missing = PriceField}])
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
John Lato | 14 Aug 02:21 2014
Picon

Re: The Good, the Bad and the GUI

On Wed, Aug 13, 2014 at 4:21 PM, Tom Ellis <tom-lists-haskell-cafe-2013 <at> jaguarpaw.co.uk> wrote:
On Wed, Aug 13, 2014 at 10:31:31PM +0200, Wojtek Narczyński wrote:
> On 13.08.2014 12:37, Tom Ellis wrote:
> >On Tue, Aug 12, 2014 at 12:46:05PM +0200, Wojtek Narczyński wrote:
> >>Continuing my VAT Invoice example, let us say a LineItem that does
> >>not have a product description (missing value), but it does have all
> >>the numeric fields filled in.  It is partly erroneous, but it can be
> >>included in calculation of the total. How would you handle it with
> >>Either [Error] Invoice style code?
> >What sort of functionality are you looking for exactly?  What's your
> >objection to (for example)
> >
> >     data LineItemGeneral a = LineItem { price :: Price
> >                                       , quantity :: Quantity
> >                                       , description :: a }
> >
> >     type LineItem = LineItemGeneral String
> >     type LineItemPossiblyIncomplete = LineItemGeneral (Maybe String)
> >     type LineItemWithoutDescription = LineItemGeneral ()
> >
> >     totalValue :: LineItemGeneral a -> Value
> >     totalValue lineItem = price lineItem * quantity lineItem
> >
> >`totalValue` works for all sorts of line items, whether they have a
> >description or not.
>
> Let's say the user entered:
>
> No, Name, Qty, Price
> --------------------------------------------
> 1. [        ]   [99] [10]
> 2. [Water] [    ] [10]
> 3. [Juice]   [  1] [    ]
>
> The GUI should display total of 990, and signal four errors: three
> missing values (ideally different color of the input fields), and
> the whole invoice incomplete. The Either [Error] Invoice type does
> not work, because can either display the errors or calculate total
> from a correct invoice, never both. And you can't even create
> LineItem for 2. and 3. Well, maybe you can with laziness, but how
> would total work then?
>
> That's why I asked in my original post, whether I'd need two types,
> one for correct complete invoice, and another for the invoice "in
> statu nascendi". And how to obtain them, lazily, and I mean the
> person, not the language.

Perhaps I don't grasp exactly what you're getting at, but this seems easy.
Please let me know where my proposed solution fails to provide what you
need.

I do see that you originally said "In Haskell you'd need two data types: the
usual proper Haskell data type, and another which wraps every field in
Maybe, facilitates editing, validation, etc.".  You don't actually *need*
the version without the Maybe, but you can provide it if you want some
additional type safety.  If you'd like to see an example of making that
nice and easy with minimal boilerplate please ask.


    import Control.Applicative
    import Data.Maybe
    import Control.Arrow

    type Quantity = Double
    type Price = Double
    type Value = Double

    data LineItem = LineItem { name :: Maybe String
                             , quantity :: Maybe Quantity
                             , price :: Maybe Price }


Rather than this definition, what about something like:

    data LineItemF f = LineItem
        { name :: f String
        , quantity :: f Quantity
        , price :: f Price }

    type LineItemBuilder = LineItemF (Writer Error)
    type LineItem = LineItemF Identity

    newLineItemBuilder :: LineItemBuilder
    newLineItemBuilder = LineItemF
        {"Missing" <$ tell (Error 1 NameField)
        ,0 <$ tell (Error 2 QuantityField)
        ,0 <$ tell (Error 3 PriceField)}

    setName :: LineItemBuilder -> String -> LineItemBuilder
    setName li newName = if validName newName
        then li { name = pure newName }
        else li -- either leave the original, or add the new name and tell another error,
                  -- depending on use case

    -- quantity,price can be set similarly

    buildLineItem :: LineItemBuilder -> Either [Error] LineItem
    buildLineItem LineItemF{name, quantity,price} = case runWriter builder of
         (built,[]) -> Right built
         (_, errs) -> Left errs
      where
        builder = LineItemF <$> (pure <$> name)
                                     <*> (pure <$> quantity)
                                     <*> (pure <$> price)

Now you have one type that represents a LineItem, and you can determine the state of the LineItem by which functor is used.  You'll probably be able to get some code re-use for any functions that don't need to know if a particular LineItem is valid or not, but there's still a type-level distinction between validated and unvalidated LineItems.  And if you're using lens, you can access the component fields with "name . _Wrapped" (or maybe _Unwrapped, depends on which version of lens you're using).

If you're taking arbitrary strings as user input, and they haven't been parsed as numbers yet (or otherwise validated), you can even handle that case by using an appropriate functor, such as "Constant String".  Then you could have a function like

    validate :: (String -> Either ValidationError a) -> Constant String a -> Either ValidationError a

that takes a parser and parses/validates the field.

John L.
 

    data Field = NameField | QuantityField | PriceField
               deriving Show

    data Error = Error { item :: Int
                       , missing :: Field }
               deriving Show

    value :: LineItem -> Maybe Value
    value l = (*) <$> price l <*> quantity l

    totalValue :: [LineItem] -> Value
    totalValue = sum . map (fromMaybe 0 . value)

    missingFields :: LineItem -> [Field]
    missingFields l = n ++ q ++ p
      where n = if name l == Nothing then [NameField] else []
            q = if quantity l == Nothing then [QuantityField] else []
            p = if price l == Nothing then [PriceField] else []

    errors :: [LineItem] -> [Error]
    errors = concatMap (\(i, es) -> map (Error i) es)
             . zip [1..]
             . map missingFields

    guiResponse :: [LineItem] -> (Value, [Error])
    guiResponse = totalValue &&& errors

    exampleData :: [LineItem]
    exampleData = [ LineItem Nothing        (Just 99) (Just 10)
                  , LineItem (Just "Water") Nothing   (Just 10)
                  , LineItem (Just "Juice") (Just 1)  Nothing ]

    -- *Main> guiResponse exampleData
    -- (990.0, [ Error {item = 1, missing = NameField}
    --         , Error {item = 2, missing = QuantityField}
    --         , Error {item = 3, missing = PriceField}])
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Tom Ellis | 14 Aug 09:19 2014
Picon

Re: The Good, the Bad and the GUI

On Wed, Aug 13, 2014 at 05:21:28PM -0700, John Lato wrote:
> On Wed, Aug 13, 2014 at 4:21 PM, Tom Ellis
> >     data LineItem = LineItem { name :: Maybe String
> >                              , quantity :: Maybe Quantity
> >                              , price :: Maybe Price }
> 
> Rather than this definition, what about something like:
> 
>     data LineItemF f = LineItem
>         { name :: f String
>         , quantity :: f Quantity
>         , price :: f Price }

It seems Wojtek already objected to this approach, though perhaps that
objection could be overcome

    http://www.haskell.org/pipermail/haskell-cafe/2014-August/115528.html
John Lato | 14 Aug 10:35 2014
Picon

Re: The Good, the Bad and the GUI

I would suggest  { someMaybeField :: f (Maybe Value) }, or perhaps newtype MaybeValue = MV (Maybe Value).


On Thu, Aug 14, 2014 at 12:19 AM, Tom Ellis <tom-lists-haskell-cafe-2013 <at> jaguarpaw.co.uk> wrote:
On Wed, Aug 13, 2014 at 05:21:28PM -0700, John Lato wrote:
> On Wed, Aug 13, 2014 at 4:21 PM, Tom Ellis
> >     data LineItem = LineItem { name :: Maybe String
> >                              , quantity :: Maybe Quantity
> >                              , price :: Maybe Price }
>
> Rather than this definition, what about something like:
>
>     data LineItemF f = LineItem
>         { name :: f String
>         , quantity :: f Quantity
>         , price :: f Price }

It seems Wojtek already objected to this approach, though perhaps that
objection could be overcome

    http://www.haskell.org/pipermail/haskell-cafe/2014-August/115528.html
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Tom Ellis | 14 Aug 10:39 2014
Picon

Re: The Good, the Bad and the GUI

On Thu, Aug 14, 2014 at 01:35:36AM -0700, John Lato wrote:
> I would suggest  { someMaybeField :: f (Maybe Value) }, or perhaps newtype
> MaybeValue = MV (Maybe Value).

That seems like a perfectly good solution to me.  The only drawback is that
you cannot validate fields individually.

Tom
Wojtek Narczyński | 14 Aug 11:28 2014
Picon

Re: The Good, the Bad and the GUI


On 14.08.2014 09:19, Tom Ellis wrote:
> On Wed, Aug 13, 2014 at 05:21:28PM -0700, John Lato wrote:
>> On Wed, Aug 13, 2014 at 4:21 PM, Tom Ellis
>>>      data LineItem = LineItem { name :: Maybe String
>>>                               , quantity :: Maybe Quantity
>>>                               , price :: Maybe Price }
>> Rather than this definition, what about something like:
>>
>>      data LineItemF f = LineItem
>>          { name :: f String
>>          , quantity :: f Quantity
>>          , price :: f Price }
> It seems Wojtek already objected to this approach, though perhaps that
> objection could be overcome
>
>
Hmm, perhaps like this

LineItemFi = LineItemFi
    { name :: StringFi
    , quantity :: QuantityFi
    , price :: PriceFi }

data LineItemUi f = LineItemUi
     { name :: StringUi
     , quantity :: QuantityUi
     , price :: PriceUi }

I mean 1:1 correspondence between leaf UI types that can be missing, 
validate lengths, etc. and final types that go to the backend. Maybe it 
would be possible to use type classes / families to have common 
arithmietics for calculating with both kinds of types. This does require 
TH or Generics, but it's fine.

--

-- 
Wojtek
Tom Ellis | 14 Aug 11:41 2014
Picon

Re: The Good, the Bad and the GUI

On Thu, Aug 14, 2014 at 11:28:53AM +0200, Wojtek Narczyński wrote:
> On 14.08.2014 09:19, Tom Ellis wrote:
> >On Wed, Aug 13, 2014 at 05:21:28PM -0700, John Lato wrote:
> >>On Wed, Aug 13, 2014 at 4:21 PM, Tom Ellis
> >>>     data LineItem = LineItem { name :: Maybe String
> >>>                              , quantity :: Maybe Quantity
> >>>                              , price :: Maybe Price }
> >>Rather than this definition, what about something like:
> >>
> >>     data LineItemF f = LineItem
> >>         { name :: f String
> >>         , quantity :: f Quantity
> >>         , price :: f Price }
> >It seems Wojtek already objected to this approach, though perhaps that
> >objection could be overcome
>
> Hmm, perhaps like this
> 
> LineItemFi = LineItemFi
>    { name :: StringFi
>    , quantity :: QuantityFi
>    , price :: PriceFi }
> 
> 
> data LineItemUi f = LineItemUi
>     { name :: StringUi
>     , quantity :: QuantityUi
>     , price :: PriceUi }

You didn't use f there.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Alberto G. Corona | 14 Aug 14:06 2014
Picon

Re: The Good, the Bad and the GUI

Formlets ever had cascade validation:

data Item= Item{ name ::String, quantity, price :: Int}

Item <$>
       <*> inputString `validate` nonEmpty
       <*> inputInt
       <*> inputInt 
 `validate` ( \item -> do
      if theUniverseIsSpanding then do
           if name item == "carrots" && price=="10" then
                       fail "we don´t like 10 cent carrots  in an expanding universe"
           else if.....


2014-08-14 11:41 GMT+02:00 Tom Ellis <tom-lists-haskell-cafe-2013 <at> jaguarpaw.co.uk>:
On Thu, Aug 14, 2014 at 11:28:53AM +0200, Wojtek Narczyński wrote:
> On 14.08.2014 09:19, Tom Ellis wrote:
> >On Wed, Aug 13, 2014 at 05:21:28PM -0700, John Lato wrote:
> >>On Wed, Aug 13, 2014 at 4:21 PM, Tom Ellis
> >>>     data LineItem = LineItem { name :: Maybe String
> >>>                              , quantity :: Maybe Quantity
> >>>                              , price :: Maybe Price }
> >>Rather than this definition, what about something like:
> >>
> >>     data LineItemF f = LineItem
> >>         { name :: f String
> >>         , quantity :: f Quantity
> >>         , price :: f Price }
> >It seems Wojtek already objected to this approach, though perhaps that
> >objection could be overcome
>
> Hmm, perhaps like this
>
> LineItemFi = LineItemFi
>    { name :: StringFi
>    , quantity :: QuantityFi
>    , price :: PriceFi }
>
>
> data LineItemUi f = LineItemUi
>     { name :: StringUi
>     , quantity :: QuantityUi
>     , price :: PriceUi }

You didn't use f there.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Alberto.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 14 Aug 14:19 2014
Picon

Re: The Good, the Bad and the GUI


On 14.08.2014 14:06, Alberto G. Corona wrote:
> Formlets ever had cascade validation:
>
>

If you put validation into the UI, you are unable to reuse it.

--

-- 
Wojtek
John Lato | 15 Aug 02:00 2014
Picon

Re: The Good, the Bad and the GUI

This is starting to look promising.  I think what would be really interesting would be to abstract out the validation logic so that it could be presented in a more declarative fashion, something like

    itemPrice *> \item inputPrice ->
        if inputPrice > 0 then return inputPrice
            else fail ("invalid item price for item " ++ show (item,inputPrice))

    itemTotal *> \item _ -> do
        price <- need $ itemPrice item
        qty <- need $ itemQty item
        return $ price * qty

    itemizedVat *> \item _ -> do
        vatExempt <- need $ vatStatus . client . invoice $ item
        if vatExempt then return 0 else do
            total <- need $ itemTotal item
            rate <- need $ vatRate item
            return $ calcVatForValue total rate

    total *> \invoice _ -> do
        itemTotals <- forM (items invoice) $ \item -> (,) <$> need (itemTotal item) <*> need (itemizedVat item)
        let (itemVals,vatVals) = unzip itemTotals
            subTotal = sum itemVals
            vatTotal = sum vatVals
        return $ Total { subTotal, vatTotal, fullTotal = subTotal+vatTotal }

Inspired by the shake build system.  Off the top of my head, so there's no system I know of that implements something like this.  But it might be a nice way to declare complex validation rules, perhaps?  Error handling could be handled by individual rules, so we know if there's a valid itemPrice and itemQty, the itemTotal is valid too.

It might be tricky to implement this exactly as-is, I'm using "itemTotal" as both a tag to specify a rule match and also a field name.  And typing some of the input/output stuff might be non-trivial.  Seems like something that could benefit from a specialized DSL.

John L.

On Thu, Aug 14, 2014 at 5:06 AM, Alberto G. Corona <agocorona <at> gmail.com> wrote:
Formlets ever had cascade validation:

data Item= Item{ name ::String, quantity, price :: Int}

Item <$>
       <*> inputString `validate` nonEmpty
       <*> inputInt
       <*> inputInt 
 `validate` ( \item -> do
      if theUniverseIsSpanding then do
           if name item == "carrots" && price=="10" then
                       fail "we don´t like 10 cent carrots  in an expanding universe"
           else if.....


2014-08-14 11:41 GMT+02:00 Tom Ellis <tom-lists-haskell-cafe-2013 <at> jaguarpaw.co.uk>:

On Thu, Aug 14, 2014 at 11:28:53AM +0200, Wojtek Narczyński wrote:
> On 14.08.2014 09:19, Tom Ellis wrote:
> >On Wed, Aug 13, 2014 at 05:21:28PM -0700, John Lato wrote:
> >>On Wed, Aug 13, 2014 at 4:21 PM, Tom Ellis
> >>>     data LineItem = LineItem { name :: Maybe String
> >>>                              , quantity :: Maybe Quantity
> >>>                              , price :: Maybe Price }
> >>Rather than this definition, what about something like:
> >>
> >>     data LineItemF f = LineItem
> >>         { name :: f String
> >>         , quantity :: f Quantity
> >>         , price :: f Price }
> >It seems Wojtek already objected to this approach, though perhaps that
> >objection could be overcome
>
> Hmm, perhaps like this
>
> LineItemFi = LineItemFi
>    { name :: StringFi
>    , quantity :: QuantityFi
>    , price :: PriceFi }
>
>
> data LineItemUi f = LineItemUi
>     { name :: StringUi
>     , quantity :: QuantityUi
>     , price :: PriceUi }

You didn't use f there.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Alberto.

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 14 Aug 10:48 2014
Picon

Re: The Good, the Bad and the GUI

On 14.08.2014 01:21, Tom Ellis wrote:
>
> Perhaps I don't grasp exactly what you're getting at, but this seems easy.
> Please let me know where my proposed solution fails to provide what you
> need.
>
> I do see that you originally said "In Haskell you'd need two data types: the
> usual proper Haskell data type, and another which wraps every field in
> Maybe, facilitates editing, validation, etc.".  You don't actually *need*
> the version without the Maybe, but you can provide it if you want some
> additional type safety.

Yes! This is what I mean.

But there is much more to validation, than just missing values. For text 
fields you have lengths, regexps. For numeric fields you have ranges, 
steps. Then come rules that are inter-fleld: if this field is "Yes", 
that field must be filled, if the user chooses "No" a field should be 
hidden, if the user changes his mind, the value entered should be 
preserved (not validation, but related). Then come rules that are 
inter-record: if this field is "ExportInvoice", all VAT fields in the 
LineItem must be zero.

The difficulty lies in abundance, ubiquity and complexity of the 
validation rules.

Empty fields are just an innocent example. The code you provided solves 
it well, but this is just a tip of an iceberg.

And we still haven't even touched the subject of assisting the user to 
fix the inconsistencies.

Therefore, quite frankly, I was hoping for radical new ideas how to 
tackle this, when I was starting this thread. DSLs, logic, Attribute 
Grammars, something like that.
Tom Ellis | 14 Aug 10:59 2014
Picon

Re: The Good, the Bad and the GUI

On Thu, Aug 14, 2014 at 10:48:34AM +0200, Wojtek Narczyński wrote:
> On 14.08.2014 01:21, Tom Ellis wrote:
> >Perhaps I don't grasp exactly what you're getting at, but this seems easy.
> >Please let me know where my proposed solution fails to provide what you
> >need.
> >
> >I do see that you originally said "In Haskell you'd need two data types: the
> >usual proper Haskell data type, and another which wraps every field in
> >Maybe, facilitates editing, validation, etc.".  You don't actually *need*
> >the version without the Maybe, but you can provide it if you want some
> >additional type safety.
> 
> Yes! This is what I mean.
> 
> But there is much more to validation, than just missing values.
[...]
> 
> The difficulty lies in abundance, ubiquity and complexity of the
> validation rules.
> 
> Empty fields are just an innocent example. The code you provided
> solves it well, but this is just a tip of an iceberg.
> 
> And we still haven't even touched the subject of assisting the user
> to fix the inconsistencies.
> 
> Therefore, quite frankly, I was hoping for radical new ideas how to
> tackle this, when I was starting this thread. DSLs, logic, Attribute
> Grammars, something like that.

Is there a language that gets this right?  If so we can try replicating its
functionality in Haskell.

Tom
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 14 Aug 11:06 2014
Picon

Re: The Good, the Bad and the GUI


On 14.08.2014 10:59, Tom Ellis wrote:
>
> Is there a language that gets this right?  If so we can try replicating its
> functionality in Haskell.
>
>
No language I know of.
ok | 14 Aug 03:22 2014
Picon

Re: The Good, the Bad and the GUI


> Let's say the user entered:
>
> No, Name, Qty, Price
> --------------------------------------------
> 1. [        ]  [99] [10]
> 2. [Water   ]  [  ] [10]
> 3. [Juice   ]  [ 1] [  ]
>
> The GUI should display total of 990,

Why?  Let's be clear about this: given that
information, the total is unknown and unknowable,
and even if lines 1 and 2 were intended to be the
same line, the existence of line 3 means that 990
is almost surely LESS than the correct total,
whatever that might be.

Supermarkets here don't let you create invoice lines
by reference (giving a possibly garbled name) but
only by ostension ("I want to buy THIS").  This is
why all those bar codes and thingies exist.
Libraries here do something similar with books:
you show the machine "I want to borrow THIS book"
and a guaranteed valid line is created.

A GUI clearly *could* be designed to allow badly
messed up entries like that, but it is at least
questionable whether it *should*.

A possible data point:  students here are very much
used to the instant feedback provided by syntax colouring
editors, and few of them would willingly program without
such tools.  (I'm annoyed by and slowed by this nonsense, but
tastes vary.)  This is evidence that at least some people
strongly prefer instant feedback; by the time they get to
the end of a form they know that each and every field is
at least plausible taken by itself.

 and signal four errors: three
> missing values (ideally different color of the input fields), and the
> whole invoice incomplete. The Either [Error] Invoice type does not work,
> because can either display the errors or calculate total from a correct
> invoice, never both. And you can't even create LineItem for 2. and 3.
> Well, maybe you can with laziness, but how would total work then?
>
> That's why I asked in my original post, whether I'd need two types, one
> for correct complete invoice, and another for the invoice "in statu
> nascendi". And how to obtain them, lazily, and I mean the person, not
> the language.
>
> --
> Wojtek
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe <at> haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
Wojtek Narczyński | 14 Aug 10:42 2014
Picon

Re: The Good, the Bad and the GUI

On 14.08.2014 03:22, ok <at> cs.otago.ac.nz wrote:
>> Let's say the user entered:
>>
>> No, Name, Qty, Price
>> --------------------------------------------
>> 1. [        ]  [99] [10]
>> 2. [Water   ]  [  ] [10]
>> 3. [Juice   ]  [ 1] [  ]
>>
>> The GUI should display total of 990,
> Why?  Let's be clear about this: given that
> information, the total is unknown and unknowable,
> and even if lines 1 and 2 were intended to be the
> same line, the existence of line 3 means that 990
> is almost surely LESS than the correct total,
> whatever that might be.

Because this is what you would get in the most familiar software for 
accountants, and the most widespread functional language in the world: a 
spreadsheet. Or simply because this has been specified this way and the 
developer is supposed to implement it.

> Supermarkets here don't let you create invoice lines
> by reference (giving a possibly garbled name) but
> only by ostension ("I want to buy THIS").  This is
> why all those bar codes and thingies exist.
> Libraries here do something similar with books:
> you show the machine "I want to borrow THIS book"
> and a guaranteed valid line is created.

Imagine you are a freelance programmer and you are in the process of 
invoicing your customer.

> A possible data point:  students here are very much
> used to the instant feedback provided by syntax colouring
> editors, and few of them would willingly program without
> such tools.  (I'm annoyed by and slowed by this nonsense, but
> tastes vary.)
Heh, I also like syntax colouring editors, vim specifically. Recently I 
saw SublimeText, and I also liked it very much, I almost switched from 
vim. I keep promising to myself that I would learn Emacs. I don't like 
Eclipse, because it is too slow.

>    This is evidence that at least some people
> strongly prefer instant feedback; by the time they get to
> the end of a form they know that each and every field is
> at least plausible taken by itself.
>
>
So in the end you admit that my "design" (scratch, rather) might be what 
young people might like?

--

-- 
Kind regards,
Wojtek Narczynski
ok | 14 Aug 16:44 2014
Picon

Re: The Good, the Bad and the GUI

> On 14.08.2014 03:22, ok <at> cs.otago.ac.nz wrote:
>>> Let's say the user entered:
>>>
>>> No, Name, Qty, Price
>>> --------------------------------------------
>>> 1. [        ]  [99] [10]
>>> 2. [Water   ]  [  ] [10]
>>> 3. [Juice   ]  [ 1] [  ]
>>>
>>> The GUI should display total of 990,
>> Why?  Let's be clear about this: given that
>> information, the total is unknown and unknowable,
>> and even if lines 1 and 2 were intended to be the
>> same line, the existence of line 3 means that 990
>> is almost surely LESS than the correct total,
>> whatever that might be.
>
> Because this is what you would get in the most familiar software for
> accountants, and the most widespread functional language in the world: a
> spreadsheet. Or simply because this has been specified this way and the
> developer is supposed to implement it.

You have taught me something, and I am grateful for the
lesson, and APPALLED at the contents of the lesson.
I don't use spreadsheets, so I was unaware of this gross
and horrifying bug in them.  There is no excuse for a
spreadsheet quietly taking a never-assigned cell as zero,
but indeed it does.  WHAT THE HELL WERE THESE PEOPLE SMOKING?

It may be familiar, it may be popular, but the answer
is beyond any reasonable question simply WRONG.

As for "the developer is supposed to implement it",
next week I'll be giving my annual ethics lecture and
I'll be pointing out to students that the codes of practice
of the various professional societies all agree that your
duty goes beyond simply doing what you are told.
If you are told to write consumer software that gets its
sums wrong, you should not do it.

However, in this context, all that matters is that you
actually have TWO senses of "valid".
Data may be valid-for-sums, where missing data are defined
(wrongly, but that's your spec.) to be zero,
without actually being honest-to-goodness-valid.

The question remains whether this valid-for-sums processing
is a property of *invoices* or a property of *forms*, and I
claim that it's a property of invoice *forms* but not a
property of invoices.

That's one way to distinguish between valid-for-spreadsheet-sums
and honest-to-goodness-valid.  There are others.

Panko's paper, "What we know about spreadsheet errors"
http://panko.shidler.hawaii.edu/SSR/Mypapers/whatknow.htm
has some scary numbers.  It contains these sentences:

    In 2003, the author spoke independently with
    experienced spreadsheet auditors in two different
    companies in the United Kingdom, where certain
    spreadsheets must be audited by law.
    Each audited about three dozen spreadsheets per year.
    Both said that they had NEVER seen a major spreadsheet
    that was free of errors
    Both also indicated that about five percent of the
    spreadsheets they audited have very serious errors
    that would have had major ramifications had they
    not been caught.

(The emphasis on NEVER is mine.)  I guess now we know one
more reason why spreadsheet errors are ubiquitous: the
interface is broken by design.

> Imagine you are a freelance programmer and you are in the process of
> invoicing your customer.

I have no idea what is customary, but I for d--n sure would not
use a spreadsheet to do it!  (This being a Haskell mailing list,
I would investigate the abilities of hLedger.)

>>    This is evidence that at least some people
>> strongly prefer instant feedback; by the time they get to
>> the end of a form they know that each and every field is
>> at least plausible taken by itself.
>>
>>
> So in the end you admit that my "design" (scratch, rather) might be what
> young people might like?

On the contrary.  You are specifying a design that lets invalid data
enter into computations.  I'm saying they would like a design that
stops invalid data as early as possible.  This is close in spirit
to the Foo/FooBuilder distinction, where a Foo is never allowed to
be in an invalid state.
Wojtek Narczyński | 14 Aug 17:11 2014
Picon

Re: The Good, the Bad and the GUI

On 14.08.2014 16:44, ok <at> cs.otago.ac.nz wrote:
> It may be familiar, it may be popular, but the answer
> is beyond any reasonable question simply WRONG.

The exactly advantage of a purpose built app over a spreadsheet is that 
it would not let you save the invoice in this state. Indeed, perhaps it 
is a good idea to tell the users that this sum is not their final value. 
For example display a marijuana leaf next to it. Although, I would 
rather use color for that.

> (The emphasis on NEVER is mine.)  I guess now we know one
> more reason why spreadsheet errors are ubiquitous: the
> interface is broken by design.

I like spreadsheets, but they are not an answer to every need.

>
> I have no idea what is customary, but I for d--n sure would not
> use a spreadsheet to do it!  (This being a Haskell mailing list,
> I would investigate the abilities of hLedger.)

Sorry, hledger is a double entry accounting system, it does not issue 
invoices.

>> So in the end you admit that my "design" (scratch, rather) might be what
>> young people might like?
> On the contrary. You are specifying a design that lets invalid data
> enter into computations. I'm saying they would like a design that
> stops invalid data as early as possible.  This is close in spirit
> to the Foo/FooBuilder distinction, where a Foo is never allowed to
> be in an invalid state.
>
>
Pardon me, but are you "young people"?
Raphaël Mongeau | 14 Aug 19:22 2014
Picon

Re: The Good, the Bad and the GUI

Would't this be a good solution to the partial null fields probleme?

--The field name and the value
type Field = (String,String)

--The form informations we get from the client
type FormResult = [Filed]

--An error message to send to teh client
type FormError = String

data Person = Person {
    firstName :: String
   ,lastName :: String
   ,birthDate :: Date
   ,height :: Int
   }

type PersonParseResult = Either FormError Person

--When receiving data froom the client you call this function and return the error to the client or continue normaly
getPersonneFromForm :: FormResult -> PersonParseResult

--You could go furter and do this:
class FromForm a where
    fromForm :: FormResult -> Either FormError a

instance FromForm Person where
    fromForm a = getPersonneFromForm a

--And then you could do this:
thisFunctionGetAForm :: FormResult -> HTTPResponse
thisFunctionGetAForm f =
    case (fromForm f) :: PersonParseResult of
        Left  a -> toHTTPResponse "The form is invalid"
        Right a -> toHTTPResponse "Ok, we got you"



2014-08-14 11:11 GMT-04:00 Wojtek Narczyński <wojtek <at> power.com.pl>:
On 14.08.2014 16:44, ok <at> cs.otago.ac.nz wrote:
It may be familiar, it may be popular, but the answer
is beyond any reasonable question simply WRONG.

The exactly advantage of a purpose built app over a spreadsheet is that it would not let you save the invoice in this state. Indeed, perhaps it is a good idea to tell the users that this sum is not their final value. For example display a marijuana leaf next to it. Although, I would rather use color for that.


(The emphasis on NEVER is mine.)  I guess now we know one
more reason why spreadsheet errors are ubiquitous: the
interface is broken by design.

I like spreadsheets, but they are not an answer to every need.



I have no idea what is customary, but I for d--n sure would not
use a spreadsheet to do it!  (This being a Haskell mailing list,
I would investigate the abilities of hLedger.)

Sorry, hledger is a double entry accounting system, it does not issue invoices.


So in the end you admit that my "design" (scratch, rather) might be what
young people might like?
On the contrary. You are specifying a design that lets invalid data
enter into computations. I'm saying they would like a design that
stops invalid data as early as possible.  This is close in spirit
to the Foo/FooBuilder distinction, where a Foo is never allowed to
be in an invalid state.


Pardon me, but are you "young people"?

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
Viva Cila
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 14 Aug 20:25 2014
Picon

Re: The Good, the Bad and the GUI

W dniu 2014-08-14 19:22, Raphaël Mongeau pisze:
> Would't this be a good solution to the partial null fields probleme?

It is a solution to the null problem alone. But it is not a holistic way 
to create good GUIs. For example id doesn't touch the following 
problems: checking input for legal characters, text field lengths, 
numeric ranges, inter-field dependencies, inter-record dependencies, 
undo, saving partially filled forms to finish filling them in later, and 
probably many more.

Also, I'm after something in the spirit of Alberto's hplayground. For 
the web UI to be appealing nowadays, it has to work on the client.

http://mflowdemo.herokuapp.com/noscript/wiki/browserwidgets
https://github.com/agocorona/hplayground

--

-- 
Wojtek

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Tom Nielsen | 15 Aug 16:17 2014
Picon

Re: The Good, the Bad and the GUI

> There is no excuse for a
> spreadsheet quietly taking a never-assigned cell as zero,
> but indeed it does.

May I contribute to this interesting discussion the observation:

1
<BLANK>
3
=PRODUCT(A1:A3)

gives 3 (in Gnumeric).

So for the PRODUCT function, blanks are treated as 1.

Furthermore, you may be interested in priorknowledge's techcrunch talk in which they promised to "disrupt blanks": http://techcrunch.com/2012/09/11/prior-knowledge-a-predictive-database-for-developers/

Tom


On Thu, Aug 14, 2014 at 3:44 PM, <ok <at> cs.otago.ac.nz> wrote:
> On 14.08.2014 03:22, ok <at> cs.otago.ac.nz wrote:
>>> Let's say the user entered:
>>>
>>> No, Name, Qty, Price
>>> --------------------------------------------
>>> 1. [        ]  [99] [10]
>>> 2. [Water   ]  [  ] [10]
>>> 3. [Juice   ]  [ 1] [  ]
>>>
>>> The GUI should display total of 990,
>> Why?  Let's be clear about this: given that
>> information, the total is unknown and unknowable,
>> and even if lines 1 and 2 were intended to be the
>> same line, the existence of line 3 means that 990
>> is almost surely LESS than the correct total,
>> whatever that might be.
>
> Because this is what you would get in the most familiar software for
> accountants, and the most widespread functional language in the world: a
> spreadsheet. Or simply because this has been specified this way and the
> developer is supposed to implement it.

You have taught me something, and I am grateful for the
lesson, and APPALLED at the contents of the lesson.
I don't use spreadsheets, so I was unaware of this gross
and horrifying bug in them.  There is no excuse for a
spreadsheet quietly taking a never-assigned cell as zero,
but indeed it does.  WHAT THE HELL WERE THESE PEOPLE SMOKING?

It may be familiar, it may be popular, but the answer
is beyond any reasonable question simply WRONG.

As for "the developer is supposed to implement it",
next week I'll be giving my annual ethics lecture and
I'll be pointing out to students that the codes of practice
of the various professional societies all agree that your
duty goes beyond simply doing what you are told.
If you are told to write consumer software that gets its
sums wrong, you should not do it.

However, in this context, all that matters is that you
actually have TWO senses of "valid".
Data may be valid-for-sums, where missing data are defined
(wrongly, but that's your spec.) to be zero,
without actually being honest-to-goodness-valid.

The question remains whether this valid-for-sums processing
is a property of *invoices* or a property of *forms*, and I
claim that it's a property of invoice *forms* but not a
property of invoices.

That's one way to distinguish between valid-for-spreadsheet-sums
and honest-to-goodness-valid.  There are others.

Panko's paper, "What we know about spreadsheet errors"
http://panko.shidler.hawaii.edu/SSR/Mypapers/whatknow.htm
has some scary numbers.  It contains these sentences:

    In 2003, the author spoke independently with
    experienced spreadsheet auditors in two different
    companies in the United Kingdom, where certain
    spreadsheets must be audited by law.
    Each audited about three dozen spreadsheets per year.
    Both said that they had NEVER seen a major spreadsheet
    that was free of errors
    Both also indicated that about five percent of the
    spreadsheets they audited have very serious errors
    that would have had major ramifications had they
    not been caught.

(The emphasis on NEVER is mine.)  I guess now we know one
more reason why spreadsheet errors are ubiquitous: the
interface is broken by design.

> Imagine you are a freelance programmer and you are in the process of
> invoicing your customer.

I have no idea what is customary, but I for d--n sure would not
use a spreadsheet to do it!  (This being a Haskell mailing list,
I would investigate the abilities of hLedger.)

>>    This is evidence that at least some people
>> strongly prefer instant feedback; by the time they get to
>> the end of a form they know that each and every field is
>> at least plausible taken by itself.
>>
>>
> So in the end you admit that my "design" (scratch, rather) might be what
> young people might like?

On the contrary.  You are specifying a design that lets invalid data
enter into computations.  I'm saying they would like a design that
stops invalid data as early as possible.  This is close in spirit
to the Foo/FooBuilder distinction, where a Foo is never allowed to
be in an invalid state.


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 16 Aug 21:53 2014
Picon

Re: The Good, the Bad and the GUI

On 15.08.2014 16:17, Tom Nielsen wrote:
> > There is no excuse for a
> > spreadsheet quietly taking a never-assigned cell as zero,
> > but indeed it does.
>
> May I contribute to this interesting discussion the observation:
>
> 1
> <BLANK>
> 3
> =PRODUCT(A1:A3)
>
> gives 3 (in Gnumeric).
>
> So for the PRODUCT function, blanks are treated as 1.
>
>

At the same time
= A1 * A2 * A3
gives 0 (in OpenOffice).

This is a bit too much, even for me.
ok | 13 Aug 03:23 2014
Picon

Re: The Good, the Bad and the GUI

> On 12.08.2014 05:31, ok <at> cs.otago.ac.nz wrote:

>> Even in Visual Basic, if an object is "constructed" via a lengthy
>> sequence of steps, it is good design to distinguish between two
>> different things": a fully constructed Foo object and a FooBuilder
>> object.  Sometimes they need to be the same object, but there really
>> do need to be two *interfaces*.  Once past the construction phase,
>> you want to KNOW that the object is fully constructed, and there are
>> things the constructor might do that you DON'T want other objects to
>> do.
>
> Take a VAT Invoice as an example. You will have:
>
> Invoice, InvoiceBuilder,
> InvoiceLineItem, InvoiceLineItemBuilder,
> InvoiceCustomer, InvoiceCustomerBuilder,
> InvoiceSummary, (no Builder, as this is calculated)
> (many, many more classes in a realistic system)
>
> Now, where the rather complex validation belongs?

Follow the GRASP patterns.  Give the task to
the type/class that has enough information to do the job.
Remember, the goal is to not create invalid objects.
It makes no sense to have an Invoice validate itself,
because the whole aim is for invalid Invoices NEVER TO
EXIST.

Some validation is fairly shallow.  If you can check a
field as soon as it is typed, it might make sense to do
so.  (Or it might not.  That's a user interface design
question.)  Some validation is deeper, and can only be
done once you have full or nearly full information.
The obvious place to put deeper validation is
InvoiceBuilder; that, after all, is one of the principal
reasons to *have* an InvoiceBuilder.

By the way, I deny that you would have a delirious menagerie
of _Builder classes, as you seem to be implying.  There needs
to be something *separate* from an InvoiceLineItem that can
accumulate the information needed to build one, and can
validate that information before the thing is built, but an
InvoiceBuilder can take responsibility for building all the
components of an Invoice.

So which types/classes deserve their own _Builder and which
do not?
- First, the _Builder pattern applies for things that
  have to be built up *incrementally* and may be in
  incomplete or inconsistent states while they are being
  built.  If you can construct something all at once in a
  fully valid state, you should, and don't need a Builder.
  If you can build something in a complete valid state and
  then you want to revise it as part of normal operation,
  again you don't need a builder.
- Second, some things are "free-standing" and some only
  make sense as part of other things.  I'm not sure exactly
  what you have in mind by an InvoiceSummary, but let's
  assume that an InvoiceSummary belongs to one and only one
  Invoice and that it doesn't really make sense for an
  InvoiceSummary to exist on its own.  Then it can share
  its owner's Builder.

In OO terms, the pattern goes something like this:
  program creates an InvoiceBuilder x
  filling out and revising the form revises x.
  there is a "commit" button; when x processes that,
  it creates a new Invoice y.
  y fills itself in, calling back to x to get the
  information it needs.  y may create its dependents;
  in fact, since a dependent should be *born* knowing
  what it depends on, the dependents *can't* be created
  until y exists.  So it probably should be y that does
  the creation.
  Eventually y finishes initialising itself, and x is
  now able to make y visible elsewhere.

The term "Builder" may be a bit misleading: the job of a
Builder is to *accumulate the information needed for
complete construction*; the actual work of construction
may be done by the new object that is eventually created,
including the creation of its parts.

The key thing is that *incompletely or inconsistently objects
are never exposed*; the first time a thing is mentionable, it
is right.

> Optional / mandatory
> requirements, lengths, ranges, regexps, control sums, field
> interdependencies, autocompletes, server sent notifications? Where to
> put all of this? To regular classes, to builder classes, or to both?

There are two and only two honest answers to questions like that.
(A) This sounds like carping, not like a real question.
(B) "It depends."  Put it wherever it works best.

Invoices are actually a nice example.  I had a student once who
told me a bit about SAP.  (He made a lot more money as a SAP
expert than I make as a lecturer.)  As I understand it, one of the
key reasons to use SAP is that once a record has gone into the
data base, it cannot be changed or deleted.  It can be marked as
not to be used any more, but it can't go away.  It can be marked
as having been superseded by a corrected version, but it can't be
changed.  So if you want to create an invoice in SAP, you really
really want to use the Builder pattern (at least in spirit).
Once the various tuples that constitute the Invoice have been
inserted in the data base, changing them is very far from being
normal operation.  For SAP, at least, I can say "put all those
things anywhere you like EXCEPT in the (persistent) Invoice."

And of course in the real world, if you are old enough you have
had the experience of interacting with an InvoiceBuilder.
You the customer, in the act of buying carpet, are sitting
on one side of the desk.  On the desk is the Invoice.  On the
other side of the desk is the InvoiceBuilder, otherwise known as
"a salesman", who gathers information from you, and fills in the
invoice.  You don't interact with the Invoice.  It just sits there.
Once the Invoice leaves the desk, the information on it normally
should not change.  If it is to change, a corrected duplicate is
made, the old one crossed out, and the new one stapled to it.
Doing this might even require the customer's signature on the new one.
The rest of the business only deals with complete Invoices.

Of course, it _all_ depends.  If you are whipping up a prototype
and speed of development (so you can get to answer some high-risk
question soon) is a priority, cut all the corners you think
appropriate.
ok | 13 Aug 03:27 2014
Picon

Re: The Good, the Bad and the GUI


> On 12.08.2014 05:31, ok <at> cs.otago.ac.nz wrote:

>> Even in Visual Basic, if an object is "constructed" via a lengthy
>> sequence of steps, it is good design to distinguish between two
>> different things": a fully constructed Foo object and a FooBuilder
>> object.  Sometimes they need to be the same object, but there really
>> do need to be two *interfaces*.  Once past the construction phase,
>> you want to KNOW that the object is fully constructed, and there are
>> things the constructor might do that you DON'T want other objects to
>> do.
>
> Take a VAT Invoice as an example. You will have:
>
> Invoice, InvoiceBuilder,
> InvoiceLineItem, InvoiceLineItemBuilder,
> InvoiceCustomer, InvoiceCustomerBuilder,
> InvoiceSummary, (no Builder, as this is calculated)
> (many, many more classes in a realistic system)
>
> Now, where the rather complex validation belongs?

Follow the GRASP patterns.  Give the task to
the type/class that has enough information to do the job.
Remember, the goal is to not create invalid objects.
It makes no sense to have an Invoice validate itself,
because the whole aim is for invalid Invoices NEVER TO
EXIST.

Some validation is fairly shallow.  If you can check a
field as soon as it is typed, it might make sense to do
so.  (Or it might not.  That's a user interface design
question.)  Some validation is deeper, and can only be
done once you have full or nearly full information.
The obvious place to put deeper validation is
InvoiceBuilder; that, after all, is one of the principal
reasons to *have* an InvoiceBuilder.

By the way, I deny that you would have a delirious menagerie
of _Builder classes, as you seem to be implying.  There needs
to be something *separate* from an InvoiceLineItem that can
accumulate the information needed to build one, and can
validate that information before the thing is built, but an
InvoiceBuilder can take responsibility for building all the
components of an Invoice.

So which types/classes deserve their own _Builder and which
do not?
- First, the _Builder pattern applies for things that
  have to be built up *incrementally* and may be in
  incomplete or inconsistent states while they are being
  built.  If you can construct something all at once in a
  fully valid state, you should, and don't need a Builder.
  If you can build something in a complete valid state and
  then you want to revise it as part of normal operation,
  again you don't need a builder.
- Second, some things are "free-standing" and some only
  make sense as part of other things.  I'm not sure exactly
  what you have in mind by an InvoiceSummary, but let's
  assume that an InvoiceSummary belongs to one and only one
  Invoice and that it doesn't really make sense for an
  InvoiceSummary to exist on its own.  Then it can share
  its owner's Builder.

In OO terms, the pattern goes something like this:
  program creates an InvoiceBuilder x
  filling out and revising the form revises x.
  there is a "commit" button; when x processes that,
  it creates a new Invoice y.
  y fills itself in, calling back to x to get the
  information it needs.  y may create its dependents;
  in fact, since a dependent should be *born* knowing
  what it depends on, the dependents *can't* be created
  until y exists.  So it probably should be y that does
  the creation.
  Eventually y finishes initialising itself, and x is
  now able to make y visible elsewhere.

The term "Builder" may be a bit misleading: the job of a
Builder is to *accumulate the information needed for
complete construction*; the actual work of construction
may be done by the new object that is eventually created,
including the creation of its parts.

The key thing is that *incompletely or inconsistently objects
are never exposed*; the first time a thing is mentionable, it
is right.

> Optional / mandatory
> requirements, lengths, ranges, regexps, control sums, field
> interdependencies, autocompletes, server sent notifications? Where to
> put all of this? To regular classes, to builder classes, or to both?

There are two and only two honest answers to questions like that.
(A) This sounds like carping, not like a real question.
(B) "It depends."  Put it wherever it works best.

Invoices are actually a nice example.  I had a student once who
told me a bit about SAP.  (He made a lot more money as a SAP
expert than I make as a lecturer.)  As I understand it, one of the
key reasons to use SAP is that once a record has gone into the
data base, it cannot be changed or deleted.  It can be marked as
not to be used any more, but it can't go away.  It can be marked
as having been superseded by a corrected version, but it can't be
changed.  So if you want to create an invoice in SAP, you really
really want to use the Builder pattern (at least in spirit).
Once the various tuples that constitute the Invoice have been
inserted in the data base, changing them is very far from being
normal operation.  For SAP, at least, I can say "put all those
things anywhere you like EXCEPT in the (persistent) Invoice."

And of course in the real world, if you are old enough you have
had the experience of interacting with an InvoiceBuilder.
You the customer, in the act of buying carpet, are sitting
on one side of the desk.  On the desk is the Invoice.  On the
other side of the desk is the InvoiceBuilder, otherwise known as
"a salesman", who gathers information from you, and fills in the
invoice.  You don't interact with the Invoice.  It just sits there.
Once the Invoice leaves the desk, the information on it normally
should not change.  If it is to change, a corrected duplicate is
made, the old one crossed out, and the new one stapled to it.
Doing this might even require the customer's signature on the new one.
The rest of the business only deals with complete Invoices.

Of course, it _all_ depends.  If you are whipping up a prototype
and speed of development (so you can get to answer some high-risk
question soon) is a priority, cut all the corners you think
appropriate.
Wojtek Narczyński | 13 Aug 09:06 2014
Picon

Re: The Good, the Bad and the GUI

On 13.08.2014 03:27, ok <at> cs.otago.ac.nz wrote:
> By the way, I deny that you would have a delirious menagerie
> of _Builder classes, as you seem to be implying.
So how exactly would you store InvoiceLine-wannabe, Customer-wannabe, 
and the like, objects inside InvoiceBuilder? OO always has the same 
answer: more patterns, more classes. This is not OO list, so hereby I 
declare not to continue this fork of this thread.

Regarding SAP, ABAP is in fact a nice DSL, but did he also tell you that 
all the custom procedure names must start from 'Z'?

(VAT) Invoice, is a good example, I wish it were used more often, in 
addition to the TODO list.

--

-- 
Kind regards from the other side of Earth,
Wojtek Narczyński
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Alois Cochard | 12 Aug 11:40 2014
Picon

Re: The Good, the Bad and the GUI

I think the way Jon Sterling integrated validation in his extensible library might give some inspiration about using a similar approach to solve the specific problem you describe.

He did a great talk about it recently, I highly recommend it:

Cheers

Alois



On 11 August 2014 23:16, Wojtek Narczyński <wojtek <at> power.com.pl> wrote:
Dear All,

Haskell is great for great many areas, let me name just two: - parsers, translators, interpreters, compilers; highly concurrent systems.

Haskell is however not great for GUIs. I've been thinking a little why this is so. I think one of the reasons might be that in Haskell it is unusual to deal with data that is incomplete or otherwise erroneous. Let me try to explain, what I mean, by example. If you declare Person class in Java, you automatically get a thingy that you can readily use in UI construction, because all the fields can temporarily be null, even the required ones. In Haskell you'd need two data types: the usual proper Haskell data type, and another which wraps every field in Maybe, facilitates editing, validation, etc. Perhaps it would be possible to generate one data type from the other, or generate both from a common specification.

Let me write the same thing in other words. It is not controversial to say on this list that specifying what is correct means, is a good idea. But for GUIs, in addition to the strong type, you need another relaxed type to hold the values temporarily, until the human manages to deliver correct data, often by trial and error.

Comments welcome.

--
Kind regards,
Wojtek Narczyński

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe



--
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Daniel Gorín | 12 Aug 15:01 2014
Picon

Re: The Good, the Bad and the GUI


On 11 Aug 2014, at 23:16, Wojtek Narczyński <wojtek <at> power.com.pl> wrote:

> If you declare Person class in Java, you automatically get a thingy that you can readily use in UI
construction, because all the fields can temporarily be null, even the required ones. In Haskell you'd
need two data types: the usual proper Haskell data type, and another which wraps every field in Maybe,
facilitates editing, validation, etc. Perhaps it would be possible to generate one data type from the
other, or generate both from a common specification.

At least this part you can achieve rather easily by parametrizing each field in your record by a functor. E.g.:

data Person f
  = Person {
    firstName :: f String
  ,lastName :: f String
  ,birthDate :: f Date
  ,height :: f Int
  }

Then you get:

 - "Person Id" is a person with every field set in stone.

 - "Person Maybe" is a person with missing information.

 - Other functors can be easily defined (and then composed) to represent things such as
Mandatory/Optional, Valid/Invalid, etc.

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojciech Narczyński | 12 Aug 21:23 2014
Picon

Re: The Good, the Bad and the GUI


W dniu 2014-08-12 15:01, Daniel Gorín pisze:
> On 11 Aug 2014, at 23:16, Wojtek Narczyński <wojtek <at> power.com.pl> wrote:
>
>> If you declare Person class in Java, you automatically get a thingy that you can readily use in UI
construction, because all the fields can temporarily be null, even the required ones. In Haskell you'd
need two data types: the usual proper Haskell data type, and another which wraps every field in Maybe,
facilitates editing, validation, etc. Perhaps it would be possible to generate one data type from the
other, or generate both from a common specification.
> At least this part you can achieve rather easily by parametrizing each field in your record by a functor. E.g.:
>
> data Person f
>    = Person {
>      firstName :: f String
>    ,lastName :: f String
>    ,birthDate :: f Date
>    ,height :: f Int
>    }
>
> Then you get:
>
>   - "Person Id" is a person with every field set in stone.
>
>   - "Person Maybe" is a person with missing information.
>
>   - Other functors can be easily defined (and then composed) to represent things such as
Mandatory/Optional, Valid/Invalid, etc.
>
>
>
I saw in the presentation submitted in another post that a similar thing 
has been done in Vinyl. But this won't work so well, because in the 
"rigid" type some fields are still supposed to remain wrapped in Maybe.

--

-- 
Wojtek
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Daniel Gorín | 13 Aug 00:26 2014
Picon

Re: The Good, the Bad and the GUI


On 12 Aug 2014, at 20:23, Wojciech Narczyński <wojtek <at> power.com.pl> wrote:

> 
> W dniu 2014-08-12 15:01, Daniel Gorín pisze:
>> On 11 Aug 2014, at 23:16, Wojtek Narczyński <wojtek <at> power.com.pl> wrote:
>> 
>>> If you declare Person class in Java, you automatically get a thingy that you can readily use in UI
construction, because all the fields can temporarily be null, even the required ones. In Haskell you'd
need two data types: the usual proper Haskell data type, and another which wraps every field in Maybe,
facilitates editing, validation, etc. Perhaps it would be possible to generate one data type from the
other, or generate both from a common specification.
>> At least this part you can achieve rather easily by parametrizing each field in your record by a functor. E.g.:
>> 
>> data Person f
>>   = Person {
>>     firstName :: f String
>>   ,lastName :: f String
>>   ,birthDate :: f Date
>>   ,height :: f Int
>>   }
>> 
>> Then you get:
>> 
>>  - "Person Id" is a person with every field set in stone.
>> 
>>  - "Person Maybe" is a person with missing information.
>> 
>>  - Other functors can be easily defined (and then composed) to represent things such as
Mandatory/Optional, Valid/Invalid, etc.
>> 
>> 
>> 
> I saw in the presentation submitted in another post that a similar thing has been done in Vinyl. But this
won't work so well, because in the "rigid" type some fields are still supposed to remain wrapped in Maybe.

That’s not necessary a problem. If you add a field:

  ,favoriteNumber :: f (Maybe Int)

Then, in Person Maybe, a value of Nothing in favoriteNumber would mean “not entered” while Just
Nothing would be “none”. Maybe you have some specific problem in mind?

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wojtek Narczyński | 13 Aug 00:44 2014
Picon

Re: The Good, the Bad and the GUI


On 13.08.2014 00:26, Daniel Gorín wrote:
> On 12 Aug 2014, at 20:23, Wojciech Narczyński <wojtek <at> power.com.pl> wrote:
>
>> W dniu 2014-08-12 15:01, Daniel Gorín pisze:
>>> On 11 Aug 2014, at 23:16, Wojtek Narczyński <wojtek <at> power.com.pl> wrote:
>>>
>>>> If you declare Person class in Java, you automatically get a thingy that you can readily use in UI
construction, because all the fields can temporarily be null, even the required ones. In Haskell you'd
need two data types: the usual proper Haskell data type, and another which wraps every field in Maybe,
facilitates editing, validation, etc. Perhaps it would be possible to generate one data type from the
other, or generate both from a common specification.
>>> At least this part you can achieve rather easily by parametrizing each field in your record by a functor. E.g.:
>>>
>>> data Person f
>>>    = Person {
>>>      firstName :: f String
>>>    ,lastName :: f String
>>>    ,birthDate :: f Date
>>>    ,height :: f Int
>>>    }
>>>
>>> Then you get:
>>>
>>>   - "Person Id" is a person with every field set in stone.
>>>
>>>   - "Person Maybe" is a person with missing information.
>>>
>>>   - Other functors can be easily defined (and then composed) to represent things such as
Mandatory/Optional, Valid/Invalid, etc.
>>>
>>>
>>>
>> I saw in the presentation submitted in another post that a similar thing has been done in Vinyl. But this
won't work so well, because in the "rigid" type some fields are still supposed to remain wrapped in Maybe.
> That’s not necessary a problem. If you add a field:
>
>    ,favoriteNumber :: f (Maybe Int)
>
> Then, in Person Maybe, a value of Nothing in favoriteNumber would mean “not entered” while Just
Nothing would be “none”. Maybe you have some specific problem in mind?
>
There is such a distinction in certain DBMSes: null vs "". It is 
confusing even to developers, not to mention users.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Tom Ellis | 13 Aug 12:40 2014
Picon

Re: The Good, the Bad and the GUI

On Tue, Aug 12, 2014 at 09:23:35PM +0200, Wojciech Narczyński wrote:
> W dniu 2014-08-12 15:01, Daniel Gorín pisze:
> >On 11 Aug 2014, at 23:16, Wojtek Narczyński <wojtek <at> power.com.pl> wrote:
> >
> >>If you declare Person class in Java, you automatically get a thingy that you can readily use in UI
construction, because all the fields can temporarily be null, even the required ones. In Haskell you'd
need two data types: the usual proper Haskell data type, and another which wraps every field in Maybe,
facilitates editing, validation, etc. Perhaps it would be possible to generate one data type from the
other, or generate both from a common specification.
> >At least this part you can achieve rather easily by parametrizing each field in your record by a functor. E.g.:
> >
> >data Person f
> >   = Person {
> >     firstName :: f String
> >   ,lastName :: f String
> >   ,birthDate :: f Date
> >   ,height :: f Int
> >   }
> >
> >Then you get:
> >
> >  - "Person Id" is a person with every field set in stone.
> >
> >  - "Person Maybe" is a person with missing information.
> >
> >  - Other functors can be easily defined (and then composed) to represent things such as
Mandatory/Optional, Valid/Invalid, etc.
>
> I saw in the presentation submitted in another post that a similar
> thing has been done in Vinyl. But this won't work so well, because
> in the "rigid" type some fields are still supposed to remain wrapped
> in Maybe.

Then make the Person type completely freely polymorphic

    data Person f l b h = Person {
       firstName :: f
     , lastName :: l
     , birthDate :: b
     , height :: h
    }

I do this a lot, and with suitible type synonyms is really a nice way of
working (especially with lenses).

Tom
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Gmane