Yesod 0.9 Release Anouncement

August 29, 2011

GravatarGreg Weber

Yesod 0.9 Release

Yesod 0.9 is on hackage! This release represents a massive amount of improvements, in some cases resulting in significant API changes. We believe this release is good enough to be a 1.0 (a release to be proud of, with a stable API). But first we need you to use it for a while and give us all of your great feedback.

We had a changelog page going for a while now to keep track of changes. But here we will explain all of the changes in their full glory.

Versioning

Yesod is split into many separate packages, all eventually wrapped up by the "yesod" package itself. When we say version 0.9, we are referring to the version of the "yesod" package.

This release releases version 0.9.1 (not 0.9.0) to hackage so that release candidate users will have an easy time upgrading.

Most of the changes for this release are not part of the "yesod" package, but rather underlying packages like hamlet or yesod-forms. As such, many of these changes have been available on Hackage since before the actual 0.9 release. However, a standard usage of the "yesod" package would not notice them. For more information, please see Using non-standard package versions.

Shakespearean templates (Hamlet)

Yesod started with hamlet, which gives one the ability to just insert variables into templates as they might be used to with a dynamic language. This was so powerful that Michael made hamlet-like template languages for css and javascript. "hamlet" is the name of the html template. We are now officially adopting the term "Shakespeare" for this style of templates.

To facilitate this, the hamlet package underwent a re-organization and was broken up into separate packages: hamlet (just hamlet), shakespeare-js (julius), shakespeare-css (lucius, cassius), and xml-hamlet. And there is a shakespeare package that contains the base code for making shakespeare-style templating languages. This makes it really easy to create a new shakespeare style template for any of your templating needs.

The major addition to this release is the shakespeare-text package. shakespeare-text is a good example of how easy it is to create a new pass-through Shakespeare template language. All it does is allow you to insert variable into normal Haskell text. This is great for creating e-mail templates, but we are also exposing 2 helpers you can choose to use in your normal haskell code. st for strict text, and lt for lazy text.

{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}
import Text.Shakespeare.Text (st)
import Data.Text.IO (putStrLn)
import Prelude hiding (putStrLn)

main = do
let version = "0.9"
putStrLn [st|Yesod release #{version}|]

As with all Shakespeare templates, there is no dependency on haskell-src-extras. If you aren't using Yesod and don't mind that dependency, there are some similar packages to shakespeare-text: Interpolation, interpolatedstring-perl6, interpolatedstring-qq.

The major difference users will notice in this release the removal of directly polymorphic Hamlet. You now choose the simplest hamlet version that suits your needs so you don't have to pay in efficiency for features you aren't using. However, the real motivation was to produce better error messages. We have upgrade notes in the previous post and the book documentation has been updated.

Forms

Just like templating, forms underwent a major cleanup. Polymorphic forms were removed, which should get rid of the most annoying error message Yesod users encountered. Some functions were also renamed- see the initial release candidate anouncement for upgrade instructions.

Thanks to Luite Stegman's help, we also added a way to easily add custom verification to your forms with the following new functions: check, checkM, and checkBool. You can see the original anouncement or the updated book documentation.

WAI

wai-app-static works together with yesod-static to now automatically set proper caching headers. This will have a huge impact, because our recommended deployment approach is now to just run your binary. Apache/Nginx are no longer required for static file serving. wai-app-static also saw some other improvements to make desktop usage better- static files can be embedded directly in the executable rather than being on the filesystem.

The debug middleware now uses the new logger to print out a thread-safe log which now includes all POST parameters.

Yesod

There is built-in support for BrowserID, a next generation, finally user-friendly authentication system. Yesod has added a logging interface, allowing you to switch to any logging system you want. But we included a very simple thread-safe logger, which we plan on switching out for a faster one in the near future. The logging interface give you the option to log the file and line number using template haskell. This same technique is available for use in my recently release file-location debugging utility package.

There have been a lot of other improvements. One example is more secure client side cookies, using CBC mode instead of ECB. (Thanks to Loïc Maury.)

Scaffolding

Scaffolding is what is generated by yesod init. This is where the most noticeable Yesod improvements show up.

  • The new logger setup to use the new WAI debug middleware.
  • in development mode emails are logged instead of sent. This is actually more convenient and gets rid of the sendmail dependency for development.
  • Signal handling on unix added to scaffolder (should probably be moved out of the handler).
  • Documentation and code for deploying to Heroku (deploy/Procfile)
  • upgrade to html5boilerplate version 2, which just means use normalize.css (instead of a css reset)
  • file name changes - see the previous upgrade post
  • configurable settings - you can place settings into yaml configuration files. By default, this is done for the host, port, connection pool size, and other database settings. And you can override settings with command line switches. The default allows you to override port argument. This added flexibility now makes deploying to Heroku much more straightforward.

Persistent 0.6 Changes

Feature-wise, there were only a few additions to Persistent 0.6 The most noticeable addition is support for "OR" queries. However, the implementation has undergone a complete re-write, making Persistent more powerful and flexible, and allowing us to switch from constructors to operators.

Persistent 0.6, a re-write and a better API

Old:

selectList [PersonNameEq "bob"] [] 0 0

New:

selectList [PersonName ==. "bob"] []

We are using 2 extra characters to make the same selection. However, the separation between field and operator makes for more readable code, and we have removed one use of Template Haskell to create the constructor with an Eq postfix. Our policy on Template Haskell has always been to use it only when the same cannot be achieved without it. When Michael originally wrote Persistent, it wasn't clear to him how to implement the operator approach rather than the constructor approach. The release of the Groundhog library showed how this can be done. We had a discussion with Boris Lykah, the Groundhog author, and figured out what we could learn from Groundhog. Persistent is now using phantom types, similar to Boris's approach.

We also discussed possible APIs at length. For Persistent we settled on something that is composable in a way similar to Groundhog, but slightly more optimized for the common use case. The main difference people will notice is no more hanging zeroes! That can be seen in the example above. The zeroes represent the limit and offset. Lets see how they are handled now when you actually need them:

Old:

selectList [PersonName ==. "bob"] [] 5 5

New:

selectList [PersonName ==. "bob"] [OffsetBy 5, LimitTo 5]

More verbose when you actually need it- but still better in that case in my mind because it is now clear which is the limit and which is the offest- the reason why I used 5 for both is because I never remembered the argument order of the older style.

The old style of sorting required constructors created by Template Haskell. Here again, we used the Groundhog approach of re-using Desc and Asc constructors with the field types.

Old:

selectList [] [PersonNameAsc, PersonLastNameAsc] 0 0

New:

selectList [] [Asc PersonName, Asc PersonLastName]

This shows why we are using lists- it makes it easy to combine pieces of a query in Haskell syntax. The most common query combination is to AND multiple conditions:

selectList [PersonName ==. "bob", PersonLastName ==. "jones"] []

Lets show the OR implementation:

selectList ([PersonName ==. "bob"] ||. [PersonLastName ==. "jones"]) []

This is not a great DSL syntax- it does require parentheses. However, OR is actually a very rare use case- so we just want something that works well and is intuitive rather than the most compact notation.

Less Template Haskell is good

Persistent still requires the same basic amount of Quasi-Quoting from the user to declare datatypes.

mkPersist sqlSettings [persist|
  Person
    name String
    lastName String
|]

However, operator annotations (Update, LT, GT, etc) are no longer required, reducing what is required from users in their quasi-quoted models for the normal use case. And the Template Haskell generated is now substantially less. This should speed up compilation time and make Persistent more extensible. The Quasi-Quoting of datatypes is still important to allow for a friendly interface with easy customizations. However, it would no longer be difficult to provide a Template Haskell interface to Persistent (and we would welcome such a patch). In fact, the Template Haskell portion of persistent is an entirely separate cabal project, and one can manually declare types in the persistent style now. There are some iphone users doing this now because Template Haskell did not work on the iphone.

Limitations

MongoDB is waiting on some upstream improvements we are helping to create in the MongoDB driver. This release has been great for Mongo though- we are really excited about the ability to add custom operators to better take advantage of MongoDB.

The biggest limitation on Persistent that makes using it worse is Haskell's lack of record name-spacing.

0.9 goal accomplishments

We laid out a list of 1.0 goals after the 0.8 release. Lets go through each of them and see how things are coming along:

  • Documentation- We are really proud in the increase of breadth and quality of the documentation. We are now at the point where the book, in combination with supplemental documentation on the wiki and in blog posts is giving people the high-level documentation that they need. The most common complaint is now about the lack of detail in the haddocks. So we are going to make a push to improve the haddocks, and also link between them and the book.
  • static file caching headers support - Done (mentioned in WAI section).
  • Support for other template types as first class citizens- the templating system has undergone a re-organization that helps make the whole situation clearer, and adding new template systems should be more straightforward.
  • Easier support for faster, non-blocking Javascript loading via something akin to require.js- not yet started.
  • A complete i18n solution- shipped!
  • Reassessing our forms package- yesod-forms were re-written to produce clearer error messages and additional features were added.
  • Embedded objects in MongoDB- just started
  • Performance improvements- Kazu has been our main source of performance improvements, submitting a patch for a faster SendFile, and writing a blazing-fast logger just before this release that we will soon incorporate. As always, we eagerly tackle any reports of slow spots in the framework. Our only other planned speedup is to use a faster system for route matching.

There are some additional 1.0 goals we are considering, including:

  • easy validation of your persistent models
  • better interactions between the models and forms
  • improving the development mode experience

Thanks you, Yesoders

I am really proud that we have accomplished our most important 1.0 goals already while cramming in so many other great changes. Thanks to everyone in the community that used the bleeding edge code, contributed bug reports, asked and answered questions, submitted pull requests, weighed in on design decisions, added things to the wiki, or suggested documentation improvements- you helped make this the by far the best Yesod release ever.

Comments

comments powered by Disqus

Archives