I’ve been trying out Haskell for developing a web application, using the Yesod framework.
As you may know, Haskell is statically typed. This may sound like an inconvenience, but Haskell’s type system is very flexible and it has very powerful type-inference – meaning you don’t need to specify types manually most of the time – so in actual usage, it’s not bad at all.
Yesod expands type-safety to various bits of web programming:
- Type-safe URLs
- Type-safe DB queries
In short, these prevent a ton of errors.
Yesod has a routing mechanism similar to most web frameworks these days.
You define routes using a simple DSL, for example
/users/#UserId UserR GET POST. This defines a route which works with GET and POST methods.
#UserId part. This is a parameter. However, it’s not just a parameter definition –
#UserId is an actual type.
In your handler function, the parameter will always be a
UserId. You could also use
#Int or whatever. The value you get will be cast into the type you want, and if not possible, an error will be presented instead.
Type-safety in URLs also applies directly to generating URLs in code. If you are generating a URL for a page which requires a
UserId, it’s again checked that you have the correct type of parameter for it. Same goes if you change your routes: a very typical scenario is adding parameters to some route, and then having to find all places where it’s used. Because URL generation uses types in Yesod, you will automatically get errors from the compiler from every place where your URL generation code is incorrect.
Type-safe DB queries
Wouldn’t it be nice if you would get an error if you mistyped something in an SQL query? Or a MongoDB query?
With Yesod, you do. Your application will not compile if your DB queries are incorrect.
In addition to this, Yesod has a persistence layer which is sort of like a light weight data mapper.
The mapper does what you’d expect: Performing queries returns you nice “objects” of data. (You actually define a data type for it, but it’s kind of like a simple object if you’re not familiar with Haskell)
Let’s say that you have a User model and need to query for all users created before a certain date. The type-safety extends to this as well: Assuming you’ve defined your user’s create time field as a
UTCTime, you can only query this field with variables of the type
UTCTime, again saving you from possible errors.
With model IDs it works even better: For example with the
UserId mentioned earlier, you can simply pass it to the Yesod persistence layer, and it will always get you a
User. You can’t query for something that isn’t a
User with a
Compile time errors
As Haskell is not a dynamic language, you must compile the application in order to run it. Putting this together with Haskell’s type system again eliminates a lot of bugs, as many errors you could accidentally make will prevent the code from compiling at all.
This all may sound like a hassle when you can simply reload or restart with dynamic languages, but with Yesod it’s just a single command to compile, or if you’re using Yesod’s development server, it will compile it automatically whenever your files change.
Compile-time checked configuration and templating
Some common parts in Yesod use specialized DSLs. These are done using Template Haskell, Haskell’s metaprogramming facility. Essentially what this allows, is compile-time checking for correctness.
Have I mentioned that Haskell is great and fun? 😉
I think Yesod and Haskell brings many great ideas to the table for web development. These are just the few things I’ve found while working with it, and there’s still much more to it.
Just type-safety in URLs and compile-time checking for all this is a massive time saver when you have a mistake somewhere. Especially with URL generation, I have forgotten to change some code somewhere countless times and then only later stumbled upon it. With Yesod, I never would’ve had the problem in the first place.
Learning Haskell may be a large effort if you haven’t used functional languages, but this is just another example showing how much it’s worth.