6 ms·
Snap: A Haskell Web Framework
- Legion 16y agoI don't write Haskell, but the documentation on that page almost made me wish I did. Other projects, take notes.
- tomh- 16y agoThis kind of documentation is rare for Haskell projects, many other attempts failed silently gaining traction because documentation writing is usually the last item on the todo list for haskell projects, really glad this one took such an effort for it!
- dons 16y ago> documentation writing is usually the last item on the todo list for haskell projects That's unfair. Documentation writing is usually the last item for software developers. Full stop.
- tomh- 16y agoYes you are right, it was unfair to say that its because it is the last todo item for Haskell projects. However I feel that it is even more important for Haskell projects to actually do that last item. I've seen several webframework projects like hApps, Happstack, turbinado which are probably great pieces of software but hard to get started on. Personally for me it is a lot harder to start doing Haskell web development coming from a background of MVC based web development. Even though I know Haskell better than python or ruby, it is easier for me to pick up python or ruby frameworks because the way I think in writing web applications (which is mainly imperative). This is where great documentation comes into play. Snap framework seems to offer this transition easier, so will definitely take a peak at it!
- jamesbritt 16y agoI was trying to get going with yesod earlier this evening, and all props to Michael Snoyman, but seeing the Snap Web site makes me far more motivated to try it, and more confidence in what it does. But, as dons pointed out, crappy docs is not limited to Haskell by any means. If you want to see your project gain traction it has to be stupid easy for people to jump in and start playing, and solid Web site with serious docs is a big win there (as are project generators and copious examples).
- weavejester 16y agoI thought much the same thing. Writing good documentation is hard, and the effort that must have gone into this site is impressive. My own project documentation is admittedly nowhere near this.
- catch404 16y agohavn't yet looked at Haskell much, but I had a look at the quick start and it's really well written. The website is one of the cleanest I've seen for a framework in a while, well done on the design!
- klaut 16y agoi am not sure if it was supposed to be like this, but all i get when i visit the url, is a list of random scribd links. And the links have nothing to do with Haskell.
- dons 16y agoThat makes no sense.
- klaut 16y agothis is what i get (i just did a screengrab): http://twitpic.com/1px4b8 http://twitpic.com/1px4b8 I am confused as well.
- dons 16y agoYou're searching with google. DNS issue, and browser confused?
- klaut 16y agoNo, I did not search with google. I clicked directly on the link provided here.
- dons 16y agoThe result is a google search page.
- nostrademons 16y agoThat's not a regular Google search page - possibly a custom search engine, but regular Google looks very different.
- robryan 16y agoI noticed some type of virus recently would send you to different links instead of the ones you were searching on Google. Maybe you have some kind of extension on that?
- deleted 16y ago[deleted]
- deleted 16y ago[deleted]
- deleted 16y ago[deleted]
- plinkplonk 16y ago"its ust that putting typesignatures in comments and checking them when i write new functions has done me fine in Ruby" if you are writing type signatures anyway why not also have (a language in which) the compiler enforces them? I understand using a dynamic typed languages and not having to write type signatures. I understand using a static typed language and having to write type signatures (or having the compiler infer them) and having the compiler ensure type safety. Your approach (writing type signatures in comments and manually type checking them) seems to combine the worst of both worlds? I don't imagine many people can do type checking/inference in their heads for large code bases. Not snark. Genuinely curious as to why someone would do something like this.
- jamesbritt 16y agoWhen I've tried to explain Haskell to Ruby folks, I mention that at some point you are likely to be writing unit tests that amount to type checks. Maybe not always, or maybe not explicitly, but the value/effort ratio of writing a type signature in Haskell is at least as good as the corresponding test code you would write in Ruby. And you don't even have to write the type signature all the time, but you still get the type checking benefits.
- deleted 16y ago[deleted]
- hammerdr 16y ago
- deleted 16y ago[deleted]
- whalesalad 16y ago"An XML-based templating system for generating HTML" That turned me off immediately.
- jamesbritt 16y ago"To install Snap, simply use cabal. It’s up to you whether or not you want to use the Heist templating library. It is not required if you just want to use the rest of Snap." But I haven't seen what other options are in place for simple templating. Presumably you could use Hamlet or something, if you wire it in. It should include at least some basic string interpolation stuff so you can so simple output in a simple way.
- how_gauche 16y agoSorry you feel that way, at least it's optional. The idea is that we are interesting in doing DOM-level transformations bound to html tags and there just isn't a robust HTML5 DOM parser available for Haskell.
- jamesbritt 16y agoWhat would you suggest for "populate placeholders in a string and send it out" page rendering?
- how_gauche 16y agoI personally like http://hackage.haskell.org/package/HStringTemplate http://hackage.haskell.org/package/HStringTemplate for that.
- jamesbritt 16y agoThanks!
- mightybyte 16y agoWhat don't you like about XML-based templating?
- elbenshira 16y agoNow, if only I can wrap my head around freaking monads.
- die_sekte 16y agoMonads are pretty simple: Think of a monad as a spacesuite full of nuclear waste in the ocean next to a container of apples. now, you can't put oranges in the space suite or the nucelar waste falls in the ocean, but the apples are carried around anyway, and you just take what you need. (http://koweycode.blogspot.com/2007/01/think-of-monad.html http://koweycode.blogspot.com/2007/01/think-of-monad.html) That explanation is pretty good if you understand monads. Otherwise it is completely useless.
- SkyMarshal 16y agoSo you have to understand monads in order to understand the explanation that helps you understand monads? Heh...
- sjs 16y agoI must not understand monads. I thought I knew the basics of how to use them, and have used them in the little bit of Haskell I have written, but that makes no sense at all to me. What are the apples and oranges supposed to represent? Why would anyone want to put oranges in the spacesuit? When "you just take what you need", who is the "you", and are they swimming around in the ocean? Is the ocean significant at all? I might be wasting my time trying to understand this analogy. I'm not up to speed on terms Haskellers throw around such as fields, rings, category theory, etc. Haskellers are welcoming of newbies and eager to teach, but are on a vastly different level than the average developer causing some of us to feel we're not smart enough to wield Haskell. Unfortunately even some basic concepts are so abstract that trying to explain them in concrete terms often leads to gibberish such as dons' analogy there. I realize dons probably wrote that for the monad-savvy crowd as kind of an inside joke, perhaps I'd do well to just move on.
- Raphael 16y agojQuery is a monad. It's a giant scope that contains information and subroutines.
- ozataman 16y agoAmazing documentation right from the start. Kudos to all the members of the project!
- alrex021 16y agoI'd love to see mustache http://mustache.github.com/ http://mustache.github.com/ ported over to Haskell now. (Maybe this would make a good pet project.)
- jimmyjazz14 16y agoI started working on something somewhat similar to mustache for haskell a while back, though its still in the early alpha stage of development. http://github.com/jamessanders/rstemplate http://github.com/jamessanders/rstemplate
- Tichy 16y agoWhat are the benefits of mustache?
- tumult 16y agoThis looks great. If you are a non-Haskeller or only a semi-Haskeller and are wondering what technical features set this apart from other existing frameworks: The Snap framework uses a style of I/O called “iteratee I/O”. We have opted for iteratees over handle-based and lazy I/O because iteratee I/O offers better resource management, error reporting, and composability. If you're interested, you can read some in-depth stuff here: http://okmij.org/ftp/Streams.html http://okmij.org/ftp/Streams.html (these papers are somewhat famous) The Snap tutorial has a decent summary of how they work, but it doesn't provide a lot of context for why. If you are already familiar with functional programming, then you know about foldl, foldr, and left/right recursion. When processing a collection of some kind (like a list), usually you take an enumerator (the fold function or a map function, for example) and pass it an iteratee (the function that will be applied to each element) and then your work gets done and you get a result. Left fold is non-lazy, right fold and map are lazy. Because Haskell is a lazy language, there is another way to process lists lazily: with explicit recursion to the right. If you are familiar with Scheme or Lisp, it would look kind of like (define (myfunc xs) (cond ((null? xs) '()) (else (cons (+ (car xs) 1) (myfunc (cdr xs)))))) which would add 1 to each element of a list, returning a new list. In Lisp or a non-lazy Scheme, this would blow up in your face for a large list. In Haskell it's no sweat, because the list will only be processed as it is needed, and generally for control structures you have to go out of your way to make it 'space leak' (build up a bunch of unevaluated expressions and then explode when you finally evaluate it.) If you use foldr or map in Haskell, it works like this. One interesting thing about using non-explicit recursion in Haskell is that if you put a bunch of maps or folds (or with the Stream Fusion library, many different types of list operations) next to each other, the compiler will inline them together and eliminate intermediate list allocations. So you can end up writing your process as a series of discrete logical steps (from list type a, to b, to c, to d) but still get the performance of doing only one traversal. Very nice. One of the downsides is that you end up with a lazy control structure, which can be problematic when dealing with the real world. For example, when reading from a file handle, someone could move the file or delete it or something. With lazy IO, the programmer is not really controlling when the file will be read by the program. Often, this is not a problem. However, with networking and time-critical applications, it can be a big problem. Another problem is that if you need to perform allocations (like going from a list of one length to a list of another length) in the middle of your transformations, it gets really tricky if you want to maintain fusion. Normally with explicit right recursion you can just cons together a larger list on the fly, but we can't do fusion on explicit recursion, and compilers are generally bad about figuring out what kinds of allocation our explicitly recursing function does. We don't want to give up our elegant way of expressing operations of sequences, but we want to know when we are writing and reading from the real world, and we want to do it with determinate constant space. Iteratees let us do that almost as elegantly as the normal list stuff by driving the consuming of the list via the functions that do the actual processing. Sort of like a list unfold, but not quite. Check out attoparsec-iteratee http://hackage.haskell.org/package/attoparsec-iteratee http://hackage.haskell.org/package/attoparsec-iteratee for an example of iteratee usage: it turns a fast bytestring parser into one that's based on iteratees, which will probably end up being even faster. (correction: which will allow you to process streams in constant space without needing to explicitly manage things.) (If Dons or Gregory Collins is around to correct the numerous mistakes I'm sure I made in this post, please do so!)
- crazydiamond 16y agoI had a look at the benchmarks. Could someone confirm -- larger values (bars) means better. So RoR is the worst, and Snap the best on both benchmarks.
- chriseidhof 16y agoYes, it's the number of requests handled. More requests served is better.
- acangiano 16y agoWhat was the deployment stack like for Rails? The numbers are way off.
- rufugee 16y agoAgreed...I'm surprised Rails is SOOOO far behind everyone else.
- mightybyte 16y agoI downloaded Rails, followed a few online tutorials to build the app, and ran script/server to run the server. As mentioned in the benchmarking document, we're not experts on Rails deployment and will gladly accept suggestions for improvements that can be implemented in a few minutes.
- acangiano 16y agoYou are running the benchmark with WEBrick, a slow, development only web server. For Rails you should run nginx + Passenger.
- davidmathers 16y agoFor Rails you should run nginx + Passenger No, that's for a production website and requires setup. They just need to replace webrick with thin. > gem install thin then > thin start instead of > ./script/server Simple.
- guano___ 16y agoThe example for the echohandler is wrong, to solve, replace req <- getRequest writeBS $ maybe "" id (getParam "s" req) with param <- getParam "s" writeBS $ maybe "" id param