dynamic web form generation for algebraic data types

Dear Cafe, has anyone ever attempted (and maybe succeeded) in building dynamic forms using one of the Haskell web frameworks (Yesod,Servant,...)? By "dynamic" form I mean a form that changes the number of fields based on selections the user makes in other fields of the form. For example, say one has an algebraic data type data T = Number Int | Check Bool T A form for such a type would initially consist of radio buttons or a drop-down list with options "Number" and "Check" that lets the user select the constructor. When "Number" is selected, an <input type="number"> field is shown. When "Check" is selected, an <input type="checkbox"> is displayed next to another form of this kind. In the end, one would use the GHC.Generics machinery to generate forms for a wide range of algebraic data types. I've seen this in the Clean language's iTask library [1] and it's very convenient. Of course this would involve a lot of JavaScript like document.createElement() as well as book-keeping how to re-asseble the fields into a T value upon submission. At least the latter is already handled by libraries such as yesod-form. Olaf [1] https://cloogle.org/src/#itasks/iTasks/UI/Editor/Generic [2] https://github.com/haskell-servant/servant-swagger/issues/80

Hey Olaf, This is not an answer to your question, but I was reminded of Grace[0], which is a language with a "browser"[1] that allows you to type in terms and get back webpages based on those terms "automagically", which sounds like exactly what you need. I don't know how it's implemented, so I don't know if it is actually relevant to you, but it is worth noting that Grace itself is implemented in Haskell. Cheers, Georgi [0] https://github.com/Gabriella439/grace [1] https://trygrace.dev/ On 3/2/23 12:54, Olaf Klinke wrote:
Dear Cafe,
has anyone ever attempted (and maybe succeeded) in building dynamic forms using one of the Haskell web frameworks (Yesod,Servant,...)? By "dynamic" form I mean a form that changes the number of fields based on selections the user makes in other fields of the form.
For example, say one has an algebraic data type
data T = Number Int | Check Bool T
A form for such a type would initially consist of radio buttons or a drop-down list with options "Number" and "Check" that lets the user select the constructor. When "Number" is selected, an <input type="number"> field is shown. When "Check" is selected, an <input type="checkbox"> is displayed next to another form of this kind.
In the end, one would use the GHC.Generics machinery to generate forms for a wide range of algebraic data types. I've seen this in the Clean language's iTask library [1] and it's very convenient. Of course this would involve a lot of JavaScript like document.createElement() as well as book-keeping how to re-asseble the fields into a T value upon submission. At least the latter is already handled by libraries such as yesod-form.
Olaf
[1] https://cloogle.org/src/#itasks/iTasks/UI/Editor/Generic [2] https://github.com/haskell-servant/servant-swagger/issues/80
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

On Thu, 2023-03-02 at 15:51 +0200, Georgi Lyubenov wrote:
Hey Olaf,
This is not an answer to your question, but I was reminded of Grace[0], which is a language with a "browser"[1] that allows you to type in terms and get back webpages based on those terms "automagically", which sounds like exactly what you need. I don't know how it's implemented, so I don't know if it is actually relevant to you, but it is worth noting that Grace itself is implemented in Haskell.
Cheers, Georgi
[0] https://github.com/Gabriella439/grace [1] https://trygrace.dev/
On 3/2/23 12:54, Olaf Klinke wrote:
Dear Cafe,
has anyone ever attempted (and maybe succeeded) in building dynamic forms using one of the Haskell web frameworks (Yesod,Servant,...)? By "dynamic" form I mean a form that changes the number of fields based on selections the user makes in other fields of the form.
For example, say one has an algebraic data type
data T = Number Int | Check Bool T
A form for such a type would initially consist of radio buttons or a drop-down list with options "Number" and "Check" that lets the user select the constructor. When "Number" is selected, an <input type="number"> field is shown. When "Check" is selected, an <input type="checkbox"> is displayed next to another form of this kind.
In the end, one would use the GHC.Generics machinery to generate forms for a wide range of algebraic data types. I've seen this in the Clean language's iTask library [1] and it's very convenient. Of course this would involve a lot of JavaScript like document.createElement() as well as book-keeping how to re-asseble the fields into a T value upon submission. At least the latter is already handled by libraries such as yesod-form.
Olaf
[1] https://cloogle.org/src/#itasks/iTasks/UI/Editor/Generic [2] https://github.com/haskell-servant/servant-swagger/issues/80
Thanks for the pointer! The Grace README says under Notable Omissions:
Recursion or recursive data types
Grace only supports two built-in recursive types, which are List and JSON, but does not support user-defined recursion or anonymous recursion.
User-defined datatypes
All data types in Grace are anonymous (e.g. anonymous records and anonymous unions), and there is no concept of a data declaration
The tutorial shows how Grace function inputs are mapped to forms, where functions with List input indeed have a form that is "dynamic" in the sense I defined. Otherwise there is only one input field per function argument. That means complex types are to be input in JSON syntax and parsed. Instead of a DSL, I'd prefer a shallow embedding into Haskell, so that one can leverage all the available machinery. Yet Grace already goes a long way towards what I am after. Olaf

All of this reminds me of Conal Elliott's Tangible Values.
http://conal.net/papers/Eros/
(Not for web but the idea still applies.)
Ivan
On Thu, 2 Mar 2023 at 07:02, Olaf Klinke
On Thu, 2023-03-02 at 15:51 +0200, Georgi Lyubenov wrote:
Hey Olaf,
This is not an answer to your question, but I was reminded of Grace[0], which is a language with a "browser"[1] that allows you to type in terms and get back webpages based on those terms "automagically", which sounds like exactly what you need. I don't know how it's implemented, so I don't know if it is actually relevant to you, but it is worth noting that Grace itself is implemented in Haskell.
Cheers, Georgi
[0] https://github.com/Gabriella439/grace [1] https://trygrace.dev/
On 3/2/23 12:54, Olaf Klinke wrote:
Dear Cafe,
has anyone ever attempted (and maybe succeeded) in building dynamic forms using one of the Haskell web frameworks (Yesod,Servant,...)? By "dynamic" form I mean a form that changes the number of fields based on selections the user makes in other fields of the form.
For example, say one has an algebraic data type
data T = Number Int | Check Bool T
A form for such a type would initially consist of radio buttons or a drop-down list with options "Number" and "Check" that lets the user select the constructor. When "Number" is selected, an <input type="number"> field is shown. When "Check" is selected, an <input type="checkbox"> is displayed next to another form of this kind.
In the end, one would use the GHC.Generics machinery to generate forms for a wide range of algebraic data types. I've seen this in the Clean language's iTask library [1] and it's very convenient. Of course this would involve a lot of JavaScript like document.createElement() as well as book-keeping how to re-asseble the fields into a T value upon submission. At least the latter is already handled by libraries such as yesod-form.
Olaf
[1] https://cloogle.org/src/#itasks/iTasks/UI/Editor/Generic [2] https://github.com/haskell-servant/servant-swagger/issues/80
Thanks for the pointer!
The Grace README says under Notable Omissions:
Recursion or recursive data types
Grace only supports two built-in recursive types, which are List and JSON, but does not support user-defined recursion or anonymous recursion.
User-defined datatypes
All data types in Grace are anonymous (e.g. anonymous records and anonymous unions), and there is no concept of a data declaration
The tutorial shows how Grace function inputs are mapped to forms, where functions with List input indeed have a form that is "dynamic" in the sense I defined. Otherwise there is only one input field per function argument. That means complex types are to be input in JSON syntax and parsed. Instead of a DSL, I'd prefer a shallow embedding into Haskell, so that one can leverage all the available machinery. Yet Grace already goes a long way towards what I am after.
Olaf
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

On Thu, 2023-03-02 at 07:34 -0800, Ivan Perez wrote:
All of this reminds me of Conal Elliott's Tangible Values.
(Not for web but the idea still applies.)
Ivan
Yes, the concept has been re-invented multiple times, as is the case with most good ideas. TVs are general enough to bolt a web interface on top, I guess. Seems that Conal, too, has not solved the sum type problem. The tangible value GADT https://hackage.haskell.org/package/TV-0.5.0/docs/Interface-TV-Input.html has a Pair constructor but not for Sum. I wonder whether there is a deeper categorical reason for this. So I should re-phrase my question: Has anyone extended tangible values to Generic types and given them a modern html interface? Olaf
On Thu, 2 Mar 2023 at 07:02, Olaf Klinke
wrote: On Thu, 2023-03-02 at 15:51 +0200, Georgi Lyubenov wrote:
Hey Olaf,
This is not an answer to your question, but I was reminded of Grace[0], which is a language with a "browser"[1] that allows you to type in terms and get back webpages based on those terms "automagically", which sounds like exactly what you need. I don't know how it's implemented, so I don't know if it is actually relevant to you, but it is worth noting that Grace itself is implemented in Haskell.
Cheers, Georgi
[0] https://github.com/Gabriella439/grace [1] https://trygrace.dev/
On 3/2/23 12:54, Olaf Klinke wrote:
Dear Cafe,
has anyone ever attempted (and maybe succeeded) in building dynamic forms using one of the Haskell web frameworks (Yesod,Servant,...)? By "dynamic" form I mean a form that changes the number of fields based on selections the user makes in other fields of the form.
For example, say one has an algebraic data type
data T = Number Int | Check Bool T
A form for such a type would initially consist of radio buttons or a drop-down list with options "Number" and "Check" that lets the user select the constructor. When "Number" is selected, an <input type="number"> field is shown. When "Check" is selected, an <input type="checkbox"> is displayed next to another form of this kind.
In the end, one would use the GHC.Generics machinery to generate forms for a wide range of algebraic data types. I've seen this in the Clean language's iTask library [1] and it's very convenient. Of course this would involve a lot of JavaScript like document.createElement() as well as book-keeping how to re-asseble the fields into a T value upon submission. At least the latter is already handled by libraries such as yesod-form.
Olaf
[1] https://cloogle.org/src/#itasks/iTasks/UI/Editor/Generic [2] https://github.com/haskell-servant/servant-swagger/issues/80
Thanks for the pointer!
The Grace README says under Notable Omissions:
Recursion or recursive data types
Grace only supports two built-in recursive types, which are List and JSON, but does not support user-defined recursion or anonymous recursion.
User-defined datatypes
All data types in Grace are anonymous (e.g. anonymous records and anonymous unions), and there is no concept of a data declaration
The tutorial shows how Grace function inputs are mapped to forms, where functions with List input indeed have a form that is "dynamic" in the sense I defined. Otherwise there is only one input field per function argument. That means complex types are to be input in JSON syntax and parsed. Instead of a DSL, I'd prefer a shallow embedding into Haskell, so that one can leverage all the available machinery. Yet Grace already goes a long way towards what I am after.
Olaf
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

So I should re-phrase my question: Has anyone extended tangible values to Generic types and given them a modern html interface?
I think the answer is "no"; and it would be extremely great if someone did.
But I think at least part of the problem is that one is forced to marry
oneself to a particular web framework/JavaScript library, and is therefore
immediately out of date :(
Personally, back in the day I quite like the API put out by Yesod for
auto-generating forms - https://www.yesodweb.com/book/forms - but I don't
think it quite does what you want. Maybe it's a simple adaptation, though
(of course, forcing yourself to use a particular flavour of
javascript/styling approach).
On Thu, 2 Mar 2023 at 16:41, Olaf Klinke
On Thu, 2023-03-02 at 07:34 -0800, Ivan Perez wrote:
All of this reminds me of Conal Elliott's Tangible Values.
(Not for web but the idea still applies.)
Ivan
Yes, the concept has been re-invented multiple times, as is the case with most good ideas. TVs are general enough to bolt a web interface on top, I guess.
Seems that Conal, too, has not solved the sum type problem. The tangible value GADT https://hackage.haskell.org/package/TV-0.5.0/docs/Interface-TV-Input.html has a Pair constructor but not for Sum. I wonder whether there is a deeper categorical reason for this.
So I should re-phrase my question: Has anyone extended tangible values to Generic types and given them a modern html interface?
Olaf
On Thu, 2 Mar 2023 at 07:02, Olaf Klinke
wrote: On Thu, 2023-03-02 at 15:51 +0200, Georgi Lyubenov wrote:
Hey Olaf,
This is not an answer to your question, but I was reminded of
which is a language with a "browser"[1] that allows you to type in terms and get back webpages based on those terms "automagically", which sounds like exactly what you need. I don't know how it's implemented, so I don't know if it is actually relevant to you, but it is worth noting that Grace itself is implemented in Haskell.
Cheers, Georgi
[0] https://github.com/Gabriella439/grace [1] https://trygrace.dev/
On 3/2/23 12:54, Olaf Klinke wrote:
Dear Cafe,
has anyone ever attempted (and maybe succeeded) in building dynamic forms using one of the Haskell web frameworks (Yesod,Servant,...)? By "dynamic" form I mean a form that changes the number of fields
on selections the user makes in other fields of the form.
For example, say one has an algebraic data type
data T = Number Int | Check Bool T
A form for such a type would initially consist of radio buttons or a drop-down list with options "Number" and "Check" that lets the user select the constructor. When "Number" is selected, an <input type="number"> field is shown. When "Check" is selected, an <input type="checkbox"> is displayed next to another form of this kind.
In the end, one would use the GHC.Generics machinery to generate
for a wide range of algebraic data types. I've seen this in the Clean language's iTask library [1] and it's very convenient. Of course this would involve a lot of JavaScript like document.createElement() as well as book-keeping how to re-asseble
Grace[0], based forms the
fields into a T value upon submission. At least the latter is already handled by libraries such as yesod-form.
Olaf
[1] https://cloogle.org/src/#itasks/iTasks/UI/Editor/Generic [2] https://github.com/haskell-servant/servant-swagger/issues/80
Thanks for the pointer!
The Grace README says under Notable Omissions:
Recursion or recursive data types
Grace only supports two built-in recursive types, which are List and JSON, but does not support user-defined recursion or anonymous recursion.
User-defined datatypes
All data types in Grace are anonymous (e.g. anonymous records and anonymous unions), and there is no concept of a data declaration
The tutorial shows how Grace function inputs are mapped to forms, where functions with List input indeed have a form that is "dynamic" in the sense I defined. Otherwise there is only one input field per function argument. That means complex types are to be input in JSON syntax and parsed. Instead of a DSL, I'd prefer a shallow embedding into Haskell, so that one can leverage all the available machinery. Yet Grace already goes a long way towards what I am after.
Olaf
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- Noon van der Silk, ن http://silky.github.io/ "My programming language is kindness."

Hi, Am Donnerstag, dem 02.03.2023 um 17:40 +0100 schrieb Olaf Klinke:
Has anyone extended tangible values to Generic types and given them a modern html interface?
not Haskell, but related: For the Candid Interface Description Language (https://github.com/dfinity/candid/blob/master/spec/Candid.md), which has products and sums and recursion, there is Candid UI, which builds browser forms generically. The screenshot at https://forum.dfinity.org/t/candid-ui-has-a-new-look/1887 might be helpful; the code is at https://github.com/dfinity/candid/tree/master/tools/ui It’s currently all very much tied to the DFINITY blockchain thingy, although in theory the Candid format can could be used independently (there is a Haskell implementation), and the UI components could also be extracted. So likely not directly useful to you, but certainly related work. Cheers, Joachim -- Joachim Breitner mail@joachim-breitner.de http://www.joachim-breitner.de/

Hey With the risk of being annoying, I want to point out that the Grace browser does indeed somewhat support your original use case, because I feel like it might not be something obvious (there also is not an example for it, I think). With the term ``` merge { Number: \n -> "The number is " + Real/show n , Check: \b -> if b then "checked" else "unchecked" } ``` which is equivalent to pattern matching on the input and picking a case, we get html with two radio buttons: * Check - when this is selected, the output is based on whether a checkbox is checked * Number - when this is selected, the output is based on the value in an input text field. Of course, this is still suboptimal - the input text field and checkbox are shown at all times, but I feel like I would have misrepresented the language if I did not point out it does support something like this. Cheers, Georgi On 3/2/23 17:01, Olaf Klinke wrote:
On Thu, 2023-03-02 at 15:51 +0200, Georgi Lyubenov wrote:
Hey Olaf,
This is not an answer to your question, but I was reminded of Grace[0], which is a language with a "browser"[1] that allows you to type in terms and get back webpages based on those terms "automagically", which sounds like exactly what you need. I don't know how it's implemented, so I don't know if it is actually relevant to you, but it is worth noting that Grace itself is implemented in Haskell.
Cheers, Georgi
[0] https://github.com/Gabriella439/grace [1] https://trygrace.dev/
On 3/2/23 12:54, Olaf Klinke wrote:
Dear Cafe,
has anyone ever attempted (and maybe succeeded) in building dynamic forms using one of the Haskell web frameworks (Yesod,Servant,...)? By "dynamic" form I mean a form that changes the number of fields based on selections the user makes in other fields of the form.
For example, say one has an algebraic data type
data T = Number Int | Check Bool T
A form for such a type would initially consist of radio buttons or a drop-down list with options "Number" and "Check" that lets the user select the constructor. When "Number" is selected, an <input type="number"> field is shown. When "Check" is selected, an <input type="checkbox"> is displayed next to another form of this kind.
In the end, one would use the GHC.Generics machinery to generate forms for a wide range of algebraic data types. I've seen this in the Clean language's iTask library [1] and it's very convenient. Of course this would involve a lot of JavaScript like document.createElement() as well as book-keeping how to re-asseble the fields into a T value upon submission. At least the latter is already handled by libraries such as yesod-form.
Olaf
[1] https://cloogle.org/src/#itasks/iTasks/UI/Editor/Generic [2] https://github.com/haskell-servant/servant-swagger/issues/80
Thanks for the pointer!
The Grace README says under Notable Omissions:
Recursion or recursive data types
Grace only supports two built-in recursive types, which are List and JSON, but does not support user-defined recursion or anonymous recursion.
User-defined datatypes
All data types in Grace are anonymous (e.g. anonymous records and anonymous unions), and there is no concept of a data declaration The tutorial shows how Grace function inputs are mapped to forms, where functions with List input indeed have a form that is "dynamic" in the sense I defined. Otherwise there is only one input field per function argument. That means complex types are to be input in JSON syntax and parsed. Instead of a DSL, I'd prefer a shallow embedding into Haskell, so that one can leverage all the available machinery. Yet Grace already goes a long way towards what I am after.
Olaf

Georgi, your're absolutely right and I hope that I was clear enough when stating that Grace *does* have dynamic forms, but with the limitations stated in the project README. In fact I shall study how they are realized under the hood. Noon is right in that one should be careful not to rely on the hippest JavaScript framework which will become obsolete soon. I've experiemented a little and conclude that monads provide a suitable abstraction for dynamic forms, because >>= facilitates generation of form parts conditional on results of other form evaluations. A proof-of-concept with InputT IO as the monad is published at https://hub.darcs.net/olf/GenericForm/browse/GenericForm.hs In its current state, it is capable of generating forms for types such as Either String (Int,Bool). I also realized that while Yesod's MForm is a monad (transformer), running a form produces a list of FieldView values, which the programmer must assemble into the actual form html. While hiding some fields conditionally may be feasible with yesod-form, I think forms for recursive types are out of the question. As I understand it, the monadic structure of MForm means that field values are *evaluated* conditionally, but the fields must be present statically. Maybe Michael Snoyman can weigh in on this. Olaf On Fri, 2023-03-03 at 09:58 +0200, Georgi Lyubenov wrote:
Hey
With the risk of being annoying, I want to point out that the Grace browser does indeed somewhat support your original use case, because I feel like it might not be something obvious (there also is not an example for it, I think).
With the term ``` merge { Number: \n -> "The number is " + Real/show n , Check: \b -> if b then "checked" else "unchecked" } ``` which is equivalent to pattern matching on the input and picking a case, we get html with two radio buttons: * Check - when this is selected, the output is based on whether a checkbox is checked * Number - when this is selected, the output is based on the value in an input text field.
Of course, this is still suboptimal - the input text field and checkbox are shown at all times, but I feel like I would have misrepresented the language if I did not point out it does support something like this.
Cheers, Georgi
On 3/2/23 17:01, Olaf Klinke wrote:
On Thu, 2023-03-02 at 15:51 +0200, Georgi Lyubenov wrote:
Hey Olaf,
This is not an answer to your question, but I was reminded of Grace[0], which is a language with a "browser"[1] that allows you to type in terms and get back webpages based on those terms "automagically", which sounds like exactly what you need. I don't know how it's implemented, so I don't know if it is actually relevant to you, but it is worth noting that Grace itself is implemented in Haskell.
Cheers, Georgi
[0] https://github.com/Gabriella439/grace [1] https://trygrace.dev/
On 3/2/23 12:54, Olaf Klinke wrote:
Dear Cafe,
has anyone ever attempted (and maybe succeeded) in building dynamic forms using one of the Haskell web frameworks (Yesod,Servant,...)? By "dynamic" form I mean a form that changes the number of fields based on selections the user makes in other fields of the form.
For example, say one has an algebraic data type
data T = Number Int | Check Bool T
A form for such a type would initially consist of radio buttons or a drop-down list with options "Number" and "Check" that lets the user select the constructor. When "Number" is selected, an <input type="number"> field is shown. When "Check" is selected, an <input type="checkbox"> is displayed next to another form of this kind.
In the end, one would use the GHC.Generics machinery to generate forms for a wide range of algebraic data types. I've seen this in the Clean language's iTask library [1] and it's very convenient. Of course this would involve a lot of JavaScript like document.createElement() as well as book-keeping how to re-asseble the fields into a T value upon submission. At least the latter is already handled by libraries such as yesod-form.
Olaf
[1] https://cloogle.org/src/#itasks/iTasks/UI/Editor/Generic [2] https://github.com/haskell-servant/servant-swagger/issues/80
Thanks for the pointer!
The Grace README says under Notable Omissions:
Recursion or recursive data types
Grace only supports two built-in recursive types, which are List and JSON, but does not support user-defined recursion or anonymous recursion.
User-defined datatypes
All data types in Grace are anonymous (e.g. anonymous records and anonymous unions), and there is no concept of a data declaration The tutorial shows how Grace function inputs are mapped to forms, where functions with List input indeed have a form that is "dynamic" in the sense I defined. Otherwise there is only one input field per function argument. That means complex types are to be input in JSON syntax and parsed. Instead of a DSL, I'd prefer a shallow embedding into Haskell, so that one can leverage all the available machinery. Yet Grace already goes a long way towards what I am after.
Olaf
participants (5)
-
Georgi Lyubenov
-
Ivan Perez
-
Joachim Breitner
-
Noon van der Silk
-
Olaf Klinke