Library versus Framework: Yesod's Own World
December 10, 2010
I was going to put this at the end of my previous post, but it's really an important enough topic to be put in separately. There was recently a very good discussion on Reddit about different approaches to web development in Haskell, with a large focus on Snap versus Yesod. The top rated comment, from Chris Smith, made this seemingly controversial statement:
It's sort of its own country though: if you use Yesod, then there's a Yesod way to do web serving, persistence, templating... the works.
I think the discussion that followed was very good, and really made clear that there are different ways of having your "own world." However, I want to stick with this statement from Chris. He contrasted this to the other approach to web development in Haskell:
The rest of Haskell web applications is more or less similar: you grab a library for request routing, and a library for templating, and a library for persistence... and you just use them.
I agree with what Chris is saying here: Yesod is a fully baked approach that guides you through all your library choices. To be clear, it doesn't require that you use every one of its libraries. I've written a number of sites that don't store data in Persistent, simply because it wasn't the right match. If someone is absolutely in love with Heist or HSP, I won't be offended if they drop Hamlet. But Yesod is all about making a bunch of different components integrate nicely together.
To me, this is the difference between a library and a framework. I have purposely done Yesod development in a modular way: templating was put in Hamlet, storage in Persistent, routing in web-routes-quasi, and so on and so forth. If you like all of these choices, and you want a consistent system that makes it easy to use them together, then Yesod should be a perfect fit. If you want to pick and choose your libraries, you can choose Yesod, but you may be better served not going the framework route.
Now, I've said this before and offended some people, but perhaps I can clarify better this time: I think Snap is a library, not a framework. This is purely subjective, but based on the definition above, and on the observations of others, Snap gives you much more freedom about how to approach things. I don't think it's a bad thing to be a library: there are users that want that, and it is often the right approach. But at the current point in time, Snap is not trying to give you an all-in-one solution for every aspect of your web development. Note also that there are plans to add more features to Snap in the future, I am simply talkng about what's available today.
I point this out because I think it can help shed light on the difference between Yesod and Snap, and when you should use each. As a practical example: Yesod is very opinionated about how routing should work. It requires your routes to be clearly defined at compile time so it can give you type-safe URLs. On the other hand, Snap has a much more freeform approach to routing. I personally think that the type-safe URL approach is a boon to productivity, much like Haskell's type-safety keeps you from shooting yourself in the foot.
On the other hand, there are some applications that may not be able to specify all of their routes at compile time. For those, it would likely feel more natural to use Snap's routing system. It's possible to do this in Yesod: you could use MultiPiece to fake having dynamic routes, set up a subsite, or simply replace Yesod's routing system with something else. But that's not the Yesod way, and you will probably feel a little out of place trying to do it there.
And of course there are some people who just don't like type-safe URLs.
My point is, these two packages are two very different beasts, and they don't overlap as much as people seem to think they do. Yesod is really just the final glue package for a bunch of individual libraries that can easily be used with Yesod, Snap, Happstack or directly with CGI if you want. But Yesod itself is not meant to be used in other frameworks: it stands on its own, and does things its own way. I am unappologetic about that: my goal here is to create a clean, well designed, unified framework for creating web applications.
If you like it, I'm happy if you use it. If you don't, I'd like to hear why so I can improve things, but I won't be modifying things at the expense of our main goal. You can still enjoy a lot of the Yesod ecosystem with some of the packages I've spun off.
By the way, there is one thing I wish Happstack and Snap would both do: embrace WAI. If they don't like WAI as-is, then we should fix it. Sorry to pick on them here, but Snap is only now getting multipart form parsing support, while Yesod has had it for a while. If we were all using WAI, the problem could be solved once, as could GZIP compression, JSON-P support, cookie parsing, and a dozen other things. We could all pool our resources and produce high-quality, fast and stable libraries for testing and running in development mode. And we would all be able to deploy our apps to standalone servers, FastCGI, SCGI, CGI, and any other *CGI they make up in the future. In my opinion, by not using a system like that, it is in fact Snap and Happstack that are currently in their own worlds.
(By the way, to their credit, Happstack has done some work on an experimental fork that uses WAI, but it is not completely compatible with the main branch, and it has not been officially released.)