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-form
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.
Additionally, 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.
- Generate Javascript to do clientside validation and provide more user-friendly widgets, such as date pickers.
- 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.
Applicative
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.
Monadic
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.
While 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 FieldView
s created as part of the form.
Here is an example of a use case scenario built using MForm
:
(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 WForm
:
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.
blaze-markup
Blaze is another well-known library used by many different web frameworks, including Yesod, to create embedded HTML templates inside Haskell. blaze is packaged with the following features:
- 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.