Snap is relatively simple and as such easy to fully understand. But since it is a relatively simple framework, you have to mix and match other packages to get the functionality that you want.
Yesod on the other hand is very elaborate - it contains a lot of functionality and relies fairly heavily on the use of Template Haskell and Quasi-Quoting.
As with Ruby and Sinatra, it is mostly a matter of taste. Some people prefer lightweight frameworks and add the components they need, while others like to do things within one well-integrated framework.
I've used both and this is pretty from my experience.
If I can make comparisons I think:
* Yesod is like Rails w/ haml+sass (but type-safety throughout)
* Snap is like Servlets+JSP (especially wrt templating, besides that it is quite similar to Yesod)
* Happstack is like Zope w/o the frontend (mainly because it is the oldest (has a pre-Rails feel to it) and has its own in-haskell ACID db (Zope has ZoDB))
> Snap is relatively simple and as such easy to fully understand. But since it is a relatively simple framework, you have to mix and match other packages to get the functionality that you want.
I found it as hard a Yesod to get it up and running. Both suffer from old docs/tutorials/examples, both needed me to climb the daunting haskell learning curve.
> Yesod on the other hand is very elaborate - it contains a lot of functionality and relies fairly heavily on the use of Template Haskell and Quasi-Quoting.
How is that a problem? I say: "Template Haskell and Quasi-Quoting FTW!" DSLs or little interpreters are great in reducing code-size. Reducing code size is great, arguably nr.1, in reducing bugs.
> As with Ruby and Sinatra, it is mostly a matter of taste.
I suspect you mean "Rails and Sinatra".
It is not a matter of taste: Rails and Sinatra both build on the Rack interface and have several options for http servers (mongrel/webrick/thin/etc).
With Yesod and Snap you find they both have their own "Rack". Yesod has "WAI" and an http server "Warp" -- these blow every other option out of the water in terms of speed and seem to have a more clever design.
But it could be just my opinion. (I did remember reading somewhere that the Snap devs envy Yesod's speed and try to make their solution faster which is a good thing)
> Some people prefer lightweight frameworks and add the components they need, while others like to do things within one well-integrated framework.
This is mostly a matter of how you build your app: "from scratch" or "scaffolded". Both Yesod and Snap allow both ways. Scaffolding with Yesod brings you much further along the axis of "well-integratedness" then scaffolding with Snap which is obviously a win those preferring the scaffolding approach.
Snap offers heist as a default template engine. It is nothing like JSP at all, it is a pure html template engine like lift or zope's templates. There is no embedding any sort of logic or code in the template at all.
>How is that a problem? I say: "Template Haskell and Quasi-Quoting FTW!"
Using is fine, it is intended to reduce boilerplate and works well for that purpose. Yesod over-uses it where it is entirely unnecessary. You lose composability and have to learn another language.
As a reference: also think Zope's templates and Lift are like JSP. But after closer inspection is see your point that JSP allows some in-template arithmetic that other don't.
> Yesod over-uses it where it is entirely unnecessary. You lose composability and have to learn another language.
I think we can safely agree to disagree on this one. :) Small DSL is not another language in my book; "templates" do not need the same kind of composability that "code" benefits so much from. As you say, it reduces "boilerplate and works well for that purpose" -- great!
Or from the horse's mouth:
Snap: "Snap is a simple web development framework for unix systems, written in the Haskell programming language."
Source: http://snapframework.com/
The Yesod book: "The Haskell community is constantly pushing the boundaries finding the cleanest, most efficient solutions for each challenge.
The downside of such a powerful ecosystem is the complexity of choice. By using Yesod, you will already have most of the tools chosen for you, and you can be guaranteed they work together."
Source: http://www.yesodweb.com/
I am probably being entirely too harsh here. It is just that when you call something "elaborate" that is not an objective statement taken from the docs. You were probably trying to phrase things in an objective way, but I think every developer views "elaborate" as having a very bad connotation.
I also disagree with the Sinatra vs. Rails comparison for various reasons, but I don't want to spend time arguing analogies.
So not OO, and (opinion warning) a lot less "magic". Template Haskell and QuasiQuoting can be seen as "magic", but I dont think so; they are actually very transparent ways of making small DSLs (a common practice in Ruby-land) w/o the "Ruby magic" needed to create them.
So what exactly do you feel is bad about "railsishness"?
I think Rails brought a lot of sane defaults and best-practices to a web framework.. I'm not surprised to see nearly all web frameworks that came after it borrow from it. See for instance "Play" on Java/Scala -- very new, very Rails.
Your characterization of my posts as trolling is both inaccurate and unnecessary. Having a different opinion is not trolling.
Those are objective measures, but without measurements they say nothing.
Looking at the Snap framework google group there were 7 threads in March and 1 in April. Yesod has had ~15 threads in April and seems to have averaged ~2 threads/day in March.
I am busy at the moment. Perhaps you can help answer your own questions and add to this.
I think you've been displaying the inflexibility I refer to right here. "Everyone loves hamlet because I said so, if you don't love it you don't exist because I said everyone loves it". I understand you like the tools and methods you use, but your reaction to other people preferring other things appears hostile and/or dismissive. Accepting that people can like a different template engine without being objectively wrong might lead to yesod users having a plurality of template engines to choose from.
http://www.yesodweb.com/blog/2012/04/working-together
I have to say he has increased my respect for him immensely with this.i argue it is also useless.
compared to Servlets+JSP/Rails/Django all of Haskell's web frameworks are smaller-then-tiny.
but: functional programming is on the rise, haskell has become fast and robust, haskell's static typing is seen as an advantage... people want to use haskell for web programming; so haskell web frameworks are seeing growth.
to me Yesod seems to have the edge currently: it is most actively developed and discussed.
i used snap, and liked it, but having tried both i feel yesod makes more sense (maybe because i'm coming from rails).
I'm using Yesod now simply because it seemed to have the most active community and I don't mind a lot of choices being made for me, since I'm also learning Haskell at the same time. Maybe I'll feel differently later.
Happstack on the other hand ... invented type-safe routing, which I haven't seen anywhere else before it. Dynamic languages tend to have something vaguely similar you might call "named routes" but they don't provide the same static guarantees.
Happstack likes to use templates mixed in with code, which sounds insane but note that this is rather different from code mixed in with templates. This templating is type-safe and syntactically checked at compile time, and allows reusing all of Haskell rather than a limited subset, so using modules and functions these templates easily end up more modular and composable than any template language you've ever seen before. Admittedly, it's not the most designer-friendly solution (but should designers really mess with the HTML to begin with?).
Happstack likes to use a persistence system for native Haskell values. I suppose you could say this is similar to ZODB with Pyramid, although it's "on steroids" (due to Haskell).
I'm biased towards Happstack as you might notice from this post, but the point I'm trying to make is more that Happstack is non-traditional (in the tradition of Haskell!) and not quite like anything else. This is often seen as a weakness because it means it is less familiar to new users; I might wonder why they're using Haskell to begin with, then. :-)
(You could even argue that Happstack should be more familiar, to Haskell programmers, because it favors reuse of existing Haskell idioms like combinators, algebraic data types, monad transformer stacks...)
That said, if you do want a more traditional framework, Snap and Yesod are both great options.
Yesod gives you templating and persistence out of the box, but the template engine is a love it or hate it deal, and persistent isn't mature enough to use with an RDBMS backend.
Snap gives you templating, but no persistence out of the box. The template engine doesn't give you compile time type safety, but it also contains no logic, it is an html template system like lift. If you want to talk to a database, you use whatever haskell module you want, there's nothing snap-specific about it.
Happstack is basically the same deal as snap, but early on was pretty heavily focused on their own acid-state storage system. It has since become much more storage agnostic, and the acid-state storage system is used outside of happstack now.
Between happstack and snap, happstack has better docs, including tutorials on how to integrate with a ton of different web related modules (different template systems, digestive-functors, etc). Snap has a better web server underlying it, and subjectively appears to have more developers actively working on it. Because both allow you to use whatever modules you like quite easily, migrating an app from one framework to the other is pretty easy. Migrating from snap or happstack to yesod or the other way is quite a lot more effort.
How is this the case? Compare http://yesodweb.com and http://snapframework.com/ and tell me you really believe that the yesod guys are marketers?
> persistent isn't mature enough to use with an RDBMS backend.
How so? Also, Persistent is still at 0.9, so the version number would agree. Any persistence layer you use with Snap or Happstack is just as easy to use in Yesod too.
> Snap has a better web server underlying it
Again, how so?
I didn't say yesod had the best website, I said they put the most effort into marketing. Michael and Greg do a lot of talking about yesod, and are the only haskell framework attempting to draw in people from outside of haskell. You seem to have interpreted this as an insult, it was not. Usage increases with awareness.
>How so?
Unless you are using your RDBMS like a dumb storage system, then persistent doesn't provide the tools to access it. We're not talking advanced stuff here, the most basic fundamentals were done incorrectly: it requires int primary keys on all tables for crying out loud. Obviously multi-column foreign keys just went out the window then too. Of all our apps here, not even the most trivial could be ported to yesod using persistent.
>Any persistence layer you use with Snap or Happstack is just as easy to use in Yesod too.
Certainly. But the major difference between yesod and snap initially appears to be "yesod provides high level DB access and snap doesn't". This may be true of mongo DB (I have no use for it), but for an RDBMS it actually ends up being that neither provides high level DB access, and you have to use something from hackage.
>Again, how so?
Happstack's webserver has several issues, space usage being a major one. This isn't a controversial statement, Jeremy will tell you the same thing, it is why he's focusing on replacing happstack-server.
> I didn't say yesod had the best website, I said they put the most effort into marketing. Michael and Greg do a lot of talking about yesod, and are the only haskell framework attempting to draw in people from outside of haskell. You seem to have interpreted this as an insult, it was not. Usage increases with awareness.
There was a heavy implication that they market at the expense of engineer.
> Unless you are using your RDBMS like a dumb storage system, then persistent doesn't provide the tools to access it. We're not talking advanced stuff here, the most basic fundamentals were done incorrectly: it requires int primary keys on all tables for crying out loud. Obviously multi-column foreign keys just went out the window then too. Of all our apps here, not even the most trivial could be ported to yesod using persistent.
Fair enough. We try to stick to the "dumb storage system" model because it gives us a lot of flexibility and makes scaling easier. If you're integrating an existing DB, yeah, it sucks. If starting from scratch, its pretty awesome. But remember, Persistent != Yesod. You'll notice yesod-core doesn't depend on persistent at all.
> Certainly. But the major difference between yesod and snap initially appears to be "yesod provides high level DB access and snap doesn't". This may be true of mongo DB (I have no use for it), but for an RDBMS it actually ends up being that neither provides high level DB access, and you have to use something from hackage.
[[citation needed]] I think the principle difference is that Yesod plays to Haskell's strengths in being "radically typesafe". The amount of errors we see in compiled Yesod code is shockingly minimal.
I am impressed at your ability to read that which I did not write. There was no such implication, it is a criticism of happstack and snap. More talking = more users = more feedback = better framework. It is especially unfortunate that snap originally seemed to be making serious efforts at marketing, and then just sort of stopped.
>Fair enough. We try to stick to the "dumb storage system" model because it gives us a lot of flexibility and makes scaling easier
We avoid the dumb storage model because it eliminates flexibility, and forces us to re-implement database functionality in our app code. We're talking about starting from scratch, I just don't want to start by throwing away all the power of our database for nothing. Our biggest apps are only in the 10s of millions of rows range, so scaling isn't a problem. If it were, I'd be looking into actual dumb storage systems though (mongo, cassandra, etc) instead of using an RDBMS as a slower version of one.
>But remember, Persistent != Yesod. You'll notice yesod-core doesn't depend on persistent at all.
Yes, but as I said that is the big feature that yesod appears to provide vs happstack and snap. But upon closer inspection we had to go down to hdbc regardless of the framework.
>[[citation needed]] I think the principle difference is that Yesod plays to Haskell's strengths in being "radically typesafe"
Citation for what? That if you don't use persistent then yesod and happstack and snap are similar in functionality? I am not sure how to prove that, how about the other way? What other functionality does yesod offer that I am forgetting?
Yesod avoids haskell in attempting to be "radically typesafe". You get the exact same amount of type safety by using blaze-html and web-routes in happstack or snap as you do using yesod. As I mentioned before, yesod's template haskell, quasi-quotation fetish is rather controversial in haskell land. You can get the benefits yesod offers while retaining composability and the familiarity of using haskell instead learning a DSL. The amount of errors we see in compiled haskell code is minimal, it should not be shocking that this extends to yesod.
I know there was talk of switching happstack over to warp, and then more recently of writing another server instead. What is it you are planning to do better than warp, performance, correctness, features or something I'm not thinking of? Is there anything in particular that made you decide not to use warp?
Speed-wise, warp is maybe 3 times faster than Snap and Happstack in the pong test. Though, how that plays out in real world is hard to say. But, I doubt anyone is running a Haskell web server right now that needs anywhere close to 30,000+ requests/second. Of course, speed never hurts. Even if you are not doing a lot of requests per second, the totally latency per request counts for something. So, I see no reason for Happstack to be slower than it could be.
Because Happstack is based on lazy IO instead of conduits/enumerators/pipes, there is a perception that it must be leak files and RAM like crazy. But, that is not actually true. The server handles streaming files from disk fine, and even streaming files in POST/PUT to disk in a constant space. We had to be careful inside the server code to make that happen -- but the end user never has to deal with that for the most part.
One exception is when the user wants to use IO to generate a streaming response. For example, if you were wrote an algorithmic music generator that required IO and streaming an never ending MP3. To do that in happstack-server, you could need to use unsafeInterleaveIO. And, be a bit careful.
But, just because lazy IO can work, doesn't mean that something like Pipes would not be better. Happstack predates enumerators/pipes/conduits, so lazy IO was the best choice at the time :) The idea of moving Happstack away from lazy IO has been an the plate for a long time (before Snap and Yesod were even created). Originally we were going to move to the hyena backend. But then Johan went on a major yak shaving expedition and rewrote the GHC I/O manager, etc, instead of finishing hyena.
We did consider switching to warp. But there are a few reasons we decided not to:
1. The source code for warp did not fill me with confidence (yes.. entirely subjective). So, in the new (currently unnamed) happstack-server backend (which will be standalone similar to warp), I want to create a strong body of evidence that it actually works correctly.
2. I like pipes. At least, I like the way they are designed by starting with the core principles and semantics and trying to build something up that is based around solid math foundation like Category. Now, Michael Snoyman may be correct that pipes are not suitable for implementing an http proxy. Once the next pipes (that has resource finalization and exception handling) is out, I intend to discover if that is true or not (acme-http-proxy). (Once again, very subjective).
3. I want Happstack to be a stable platform. Historically, yesod has gone through a lot of radical changes. Something is there one day, and gone the next. My previous experiences trying to collaborate directly and indirectly with the yesod team have left me nervous about building on their work. The yesod project is focused on what is best for their own purposes -- which is fine. But, it means that if you are trying to build on it, you have to be ready to accept whatever may drop out of the sky tomorrow morning. (Also subjective).
4. the yesod dependency hell problem gives me concern as well. While the problems they are experiencing are fundamental to Cabal itself, they seem to be hit a lot harder than Happstack. So, until that is all sorted out, I don't want to make Happstack installs more likely to fail.
Given that warp is less than 1000 lines, it seems like the risks and loss of control involved with trying to leverage it do not really outweigh the cost of implementing a solution that is exactly what we want.
So, I am aiming for better design, performance, and correctness.
In terms of features.. I'm saving that surprise for later :)
> 2
Quite some research has been put in from the Yesod team on this matter. Michael Snoyman did not want to release Yesod 1.0 before the matter on pipes/conduits was settled.
> 3
This is because Yesod was not yet 1.0 -- the message was always that after 1.0 API breakage would only be allowed in major version jumps. (as it should)
> 4
Yups, everyone working on several big Haskell projects hopes this can soon be fixed. There's some GSoC proposal for it, I hope it gets through.
One question: would Happstack like to use Yesod's WAI? I see some progress has been made to that goal[1]. If you use WAI then your Warp competitor could also be used for Yesod.
I would tell Snap users they should use Happstack because we have a shiny 3D graphic on our homepage. That is based on my in-depth research which indicates that many people decided to use Snap because it had the prettiest homepage. :)
There are certainly many minor design decisions that you can compare. For example, last time I looked at Snap, it seemed like variables captured from the url, got mixed into the same environment as key/value pairs from the QUERY_STRING and POST data. And, they explicitly decided to provide only a Snap monad, but not a SnapT monad transformer. But, none of those are, in themselves, things that warrant switching.
You could also consider which technologies the frameworks embrace, such as Heist vs HSX. At the same time, heist is officially supported by happstack (and even documented in the crash course). A lot of the core technology like acid-state, heist, hsx, jmacro, persistent, etc, can be used with any of the frameworks.
It mostly comes down to picking the framework that is investing the future you think is most exciting.
So, if the Happstack Philosophy and Roadmap get you excited, then use Happstack. If you think Snap's vision of tomorrow is more exciting -- then use Snap.
http://www.happstack.com/C/ViewPage/5 http://www.happstack.com/C/ViewPage/7
- jeremy
(p.s. more meaningful urls are on the TODO list, but it was not critical enough to delay the launch of the new website).
This was fixed in the recent 0.8 release.
When we released to the public, Snap was the first serious high-performance Haskell web server based on left-fold enumerators to reach a usable level of maturity. We received an extremely positive reception documented both here and on reddit. That was two years ago. Fast forwarding to today, Happstack has made a lot of progress. Jeremy has done a fabulous job with the happstack tutorial. However it's still using the same lazy IO web server and still talking about changing. The API is still mostly the same except that the doc pages have been modularized in way that I find makes it harder to find what I'm looking for. I'd be tempted to say it's an objective criticism, but it could just be personal preference. It also looks like a significant amount of work has gone into web-routes and type-safe routing. This is usually marketed as being a Happstack thing, but as Jeremy recently demonstrated (https://github.com/stepcut/snap-web-routes-demo) it can easily be used in Snap apps.
During that time Snap has come a long way as well. We've ironed out a lot of bugs in the web server and associated API. A lot of thought has gone into preventing slowloris attacks, file upload vulnerabilities, and the like. We also have SSL support. Six months after we released Snap, Warp came onto the scene with better raw performance numbers, but it's not obvious to us that sacrificing the Snap web server's maturity for extra speed is in the best thing for our users.
On the high-level side, we've made great progress exploring the Heist templating paradigm. It has proven to be very flexible and have gotten a number of comments about how much users love it. You can also use Heist with Happstack, and similarly can use Snap with a different templating system. We spent at least 6-8 months designing our snaplet component system and feel that it turned out very well. Happstack doesn't have anything like this, and a number of the first things you'll likely need in building a web app on Happstack are already available on a modular basis as built-in or third-party snaplets. This is actually the heart of what we wanted to be working on when we started Snap, but we got side-tracked when we realized we weren't going to be able to use Hyena as our web server.
In summary, I would say that much of what is stated in the Happstack philosophy is also the Snap philosophy (the little False Simplicity jab at getParam has also been fixed). Moving to the five items in Happstack's roadmap, Snap already has points 2, 3, and 5 as well as some of the items in point #1. Even though it's not evident in Snap, I've always had a soft spot in my heart for acid-state, so I'm eagerly anticipating the planned replication and sharding. Snap already has an acid-state snaplet which means that it's probably easier to use acid-state in a Snap application than it is with Happstack. In my opinion, all this makes a compelling argument for Snap, but I'll echo Jeremy and conclude that if the Happstack project and community get you excited, then use Happstack. If you like what we're doing with Snap, then we'd love to have you using (and hopefully contributing to) Snap. Drop by the #snapframework IRC channel in Freenode. We're usually quite responsive.
What are the major differences between them? Is one of them a clear winner, the way Django/Rails are in Python/Ruby respectively?