12 Aug 00:16 2014

## 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.

--

--
Kind regards,
Wojtek Narczyński

_______________________________________________


12 Aug 00:25 2014

### Re: The Good, the Bad and the GUI

On Mon, Aug 11, 2014 at 6:16 PM, Wojtek Narczyński 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
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
_______________________________________________

12 Aug 00:53 2014

### 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 :
On Mon, Aug 11, 2014 at 6:16 PM, Wojtek Narczyński 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
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net

_______________________________________________

--
Alberto.
_______________________________________________

12 Aug 00:57 2014

### 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.

12 Aug 01:14 2014

### 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 :

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.
_______________________________________________

12 Aug 01:22 2014

### 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 :
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 :

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.
_______________________________________________

12 Aug 21:18 2014

### 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
>

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

12 Aug 21:59 2014

### Re: The Good, the Bad and the GUI

2014-08-12 21:18 GMT+02:00 Wojciech Narczyński :
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

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  12 Aug 22:01 2014 ### 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 : 2014-08-12 21:18 GMT+02:00 Wojciech Narczyński : 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.
_______________________________________________

12 Aug 22:51 2014

### Re: The Good, the Bad and the GUI


On 12.08.2014 22:01, Alberto G. Corona wrote:
>
> 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

12 Aug 23:27 2014

### 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 :

On 12.08.2014 22:01, Alberto G. Corona wrote:

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.
_______________________________________________

12 Aug 23:42 2014

### 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

13 Aug 00:13 2014

### 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 :
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.
_______________________________________________

13 Aug 00:56 2014

### 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.

_______________________________________________

13 Aug 11:05 2014

### 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 :
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.
_______________________________________________

13 Aug 11:54 2014

### Re: The Good, the Bad and the GUI

2014-08-13 11:05 GMT+02:00 Rik van der Kleij :
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 :

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.
_______________________________________________

13 Aug 12:34 2014

### 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 :
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 :

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.
_______________________________________________

13 Aug 13:01 2014

### 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 :
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 :

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 :

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.
_______________________________________________

12 Aug 10:31 2014

### 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

--

--
Kind regards,
Wojtek Narczyński
_______________________________________________

12 Aug 12:05 2014

### Re: The Good, the Bad and the GUI

2014-08-12 10:31 GMT+02:00 Wojtek Narczyński :
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!!

Thanks!

--
Kind regards,
Wojtek Narczyński

--
Alberto.
_______________________________________________

12 Aug 01:21 2014

### 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.

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 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.

_______________________________________________

_______________________________________________

12 Aug 11:40 2014

### Re: The Good, the Bad and the GUI

2014-08-12 1:21 GMT+02:00 Tikhon Jelvis :
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.

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 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.

_______________________________________________

--
Alberto.
_______________________________________________

12 Aug 13:03 2014

### 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
_______________________________________________

12 Aug 23:50 2014

### 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?

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

_______________________________________________

13 Aug 00:33 2014

### 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?
>
>
> 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
_______________________________________________

13 Aug 15:42 2014

### 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?
>>
>>
>> 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.)

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
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
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

_______________________________________________

13 Aug 23:19 2014

### 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
because.... how about you finish this statement, I don't know how to.

--

--
Kind reagrds,
Wojtek Narczynski

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
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
you finish this statement, I don't know how to.
>
> --
> Kind reagrds,
> Wojtek Narczynski
> _______________________________________________

_______________________________________________

14 Aug 01:19 2014

### 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
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.

14 Aug 01:23 2014

### 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
> >> 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
_______________________________________________

15 Aug 13:27 2014

### 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

_______________________________________________

16 Aug 23:51 2014

### 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

12 Aug 05:31 2014

### 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.

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

> 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.

12 Aug 09:55 2014

### 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

12 Aug 10:28 2014

### 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

_______________________________________________

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.

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
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
_______________________________________________

12 Aug 12:46 2014

### 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
> 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
_______________________________________________

12 Aug 12:54 2014

### Re: The Good, the Bad and the GUI

2014-08-12 12:46 GMT+02:00 Wojtek Narczyński :
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
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

_______________________________________________

--
Alberto.
_______________________________________________

13 Aug 12:37 2014

### 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
_______________________________________________

13 Aug 22:31 2014

### 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
_______________________________________________

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

13 Aug 23:27 2014

### 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".

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

Cheers,
Chris
_______________________________________________

14 Aug 01:21 2014

### 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

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  14 Aug 02:21 2014 ### Re: The Good, the Bad and the GUI On Wed, Aug 13, 2014 at 4:21 PM, Tom Ellis 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  14 Aug 09:19 2014 ### 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  14 Aug 10:35 2014 ### 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 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  14 Aug 10:39 2014 ### 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  14 Aug 11:28 2014 ### 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  14 Aug 11:41 2014 ### 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  14 Aug 14:06 2014 ### 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 :
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.
_______________________________________________

--
Alberto.
_______________________________________________

14 Aug 14:19 2014

### Re: The Good, the Bad and the GUI


On 14.08.2014 14:06, Alberto G. Corona wrote:
>
>

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

--

--
Wojtek

15 Aug 02:00 2014

### 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 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 :

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.
_______________________________________________

--
Alberto.

_______________________________________________

_______________________________________________

14 Aug 10:48 2014

### 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

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.

14 Aug 10:59 2014

### 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
>
> 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

Tom
_______________________________________________

14 Aug 11:06 2014

### 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
>
>
No language I know of.

14 Aug 03:22 2014

### 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,

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
> _______________________________________________
>

14 Aug 10:42 2014

### 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,
> 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

> 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

14 Aug 16:44 2014

### 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,
>> 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.

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.
that was free of errors
Both also indicated that about five percent of the
spreadsheets they audited have very serious errors
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

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.

14 Aug 17:11 2014

### 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"?

14 Aug 19:22 2014

### 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 :
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"?

_______________________________________________

--
Viva Cila
_______________________________________________

14 Aug 20:25 2014

### 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

_______________________________________________

15 Aug 16:17 2014

### 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, 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,
>> 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.

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.
that was free of errors
Both also indicated that about five percent of the
spreadsheets they audited have very serious errors
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

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.

_______________________________________________

_______________________________________________

16 Aug 21:53 2014

### 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.

13 Aug 03:23 2014

### 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?

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.

13 Aug 03:27 2014

### 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?

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.

13 Aug 09:06 2014

### 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

--

--
Kind regards from the other side of Earth,
Wojtek Narczyński
_______________________________________________

12 Aug 11:40 2014

### 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 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.

--
Kind regards,
Wojtek Narczyński

_______________________________________________

--
_______________________________________________

12 Aug 15:01 2014

### 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.

_______________________________________________

12 Aug 21:23 2014

### 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
_______________________________________________

13 Aug 00:26 2014

### 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?

_______________________________________________

13 Aug 00:44 2014

### 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.
_______________________________________________

13 Aug 12:40 2014

### 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
_______________________________________________