Minor improvement to yesod-forms: A Stack Builders open source update
Open source is the cornerstone of our consulting work, and we consider it one of our responsibilities to contribute back to the community that we depend on.
We are proud to share some of the open source contributions that we developed recently.
yesod is a well-known web framework in the Haskell community due its robustness and flexibility. One of the key components is called yesod-form, it's packaged with a lot of useful features to create HTML forms while helping keeping consistency during the serialization process. yesod-form let us use the same form for two different purposes:
- Generate an HTML form representation.
- Process the data from an upcoming request.
yesod-form provides other key features that are quoted from the Yesod Web Framework Book:
- Ensure data is valid.
- Marshal string data in the form submission to Haskell datatypes.
- Generate HTML code for displaying the form.
- Build up more complex forms by combining together simpler forms.
- Automatically assign names to our fields that are guaranteed to be unique.
Yesod-form provides different flavors of web forms. For the sake of simplicity, we are going to mention just two of them - the "applicative" and "monadic" forms.
These are the most commonly used. Applicative gives us some nice properties of letting error messages coalesce together and keep a very high-level, declarative approach.
A more powerful alternative to applicative. While this allows you more flexibility, it does so at the cost of being more verbose. Useful if you want to create forms that don’t fit into the standard two-column look.
Applicative forms syntax look very concise and readable, it's not possible to handle scenarios where a validation for a field depends upon other fields. This is where
Monadic forms are an alternative. However, as their description states, there is a cost associated:
it does so at the cost of being more verbose.
In order to reduce some of the verbosity introduced by
Monadic forms, Stack Builders pushed a PR containing a variant of a
Monadic form. This new form introduces a
WriterT to stack the
FieldViews created as part of the form. Here is an example of a use case scenario built using
(field1F, field1V) <- mreq textField MsgField1 Nothing (field2F, field2V) <- mreq (checkWith field1F textField) MsgField2 Nothing (field3F, field3V) <- mreq (checkWith field1F textField) MsgField3 Nothing return ( MyForm <$> field1F <*> field2F <*> field3F , [field1V, field2V, field3V] )
The previous example could be refactored as follows using
field1F <- wreq textField MsgField1 Nothing field2F <- wreq (checkWith field1F textField) MsgField2 Nothing field3F <- wreq (checkWith field1F textField) MsgField3 Nothing return $ MyForm <$> field1F <*> field2F <*> field3F
As readers can tell, the code is more compact - not exactly like the
Applicative style, but at least there is no need to collect all generated fields manually.
For more details about the implementation check the PR.
- Pretty fast – have a look at our benchmarks.
- Lightweight DSL syntax.
- Embedded in Haskell.
- Efficient Unicode support.
- Supports HTML 4 Strict and HTML 5.
- Tool to create code from an HTML file.
As GHC evolves, more types are been introduced to its core library called base. One of those is Natural which is a
Type representing arbitrary-precision non-negative integers according to its description.
blaze-markup provides a mechanism to transform Haskell data types into markup values, using a type class called
ToMarkup. blaze-markup defined some
ToMarkup instances for most common Haskell base types. Here at Stack Builders we submitted a PR introducing an instance of
ToMarkup for Natural.
For more details about the implementation see the PR with the code that we added to blaze-markup.