10 ms·
The Haskell / Snap ecosystem is as productive (or more) than Ruby/Rails.
- batista 14y agoUntil it has produced as many sites, I consider any such statements as anecdotal. That is, I'd rather measure a system's productivity with actual production in the wild than with any of the systems "inherent" capabilities. It might be productive for the author, but I don't see the general web programming public finding it more productive. People have learned Ruby to use Rails, but not many have ventured to learn Haskell to use its frameworks.
- soc88 14y agoSo basically vanilla PHP has won in your opinion, with Ruby not even being a small glimpse on the map?
- batista 14y agoIf we are empiricists, yes. And I say that as a Django man. If we are to held an idealist view, no. But it would just be ideology making up for a lack of the same volume of production being done with Ruby compared to PHP. Remember the "worse is better" motto? Worse could also be more productive. Now, I don't care why PHP is more productive in actual volume of production --instead of more productive as in "it makes you more efficient". It could be because of "stupid" programmers that cannot adapt to Ruby, because of inertia, because it is fast to start with, because it has a more vibrant ecosystem than Ruby/RoR, because of large amounts of code already built with it used to bootstrap newer projects, because of lack of RoR publicity, because of just being there first, etc etc. Thing is: by usage and number-of-sites metrics, it is.
- Marwy 14y agoIt's not as popular therefore it's not as good. Your logic is definitely valid!
- batista 14y ago>It's not as popular therefore it's not as good. Your logic is definitely valid! And your logic is definitely faulty. I've never used the word "good" What I said is "more productive" (what the author claims) can only be measured in actual PRODUCTION. That is, the important thing is not: (a) "If I were to use X framework/language, how productive would I be over Y framework/language?", but: (b) "In an actual empirical observation, what framework/language is actually responsible for the largest volume of production?" The author talks about (a), and advocates Haskell. But that is not an empirical, scientific, measurable observation, it's just his personal opinions, feelings and anecdotes. Only (b) gives an actual overall metric of the productivity of two frameworks/languages combos. Even having the same person doing the exact same project with both X and Y framework/languages and comparing the speed with which each was done, would tell us very little. Maybe someone he was more comfortable with one or the other, maybe that particular project fitted especially X over Y, maybe it didn't need to communicate with legacy stuff with neither X nor Y do well, etc. The only way to tell what generally was for production for the majority of people, is to, DUH, see what the majority of people have used for their productions.
- wylie 14y agoThis article was interesting, having only used frameworks that either do everything or just the minimum (think Rails vs Sinatra, or Django vs Tornado). I was beginning to wonder if there was a middle ground in web frameworks. The idea of a web library, not a framework, really appeals to me. Is there anything like Snap for Python or Ruby?
- zeemonkee 14y agoProbably the closest match to Snap (based on the OP's description) in Python is Pyramid: http://docs.pylonsproject.org/en/latest/docs/pyramid.html http://docs.pylonsproject.org/en/latest/docs/pyramid.html The routing system in particular looks quite similar.
- SkyMarshal 14y agoNot sure about Python and Ruby but much of the Clojure web ecosystem takes the 'library, not framework' approach.
- lucian1900 14y agowerkzeug is a nice web library and Flask merely collects several existing libraries (werkzeug, jinja2, sqlalchemy, wtforms).
- jvdongen 14y agoI've noted that split as well - and wondered indeed if there is no middle ground. Recently it occurred to me that perhaps there is no real need for that middle ground. The fact that Django comes with even more batteries included than Python itself does not mean you have to use each and every battery. And ignoring stuff you don't need is often easier than extending an even moderately complex 'middle ground framework' in a meaningful way without making a mess of it. If I compare that to my own experience, that is exactly what I've started to do over time. A thing I've become accustomed to is splitting my applications cleanly in 'front-end' (focus on interaction with humans) and 'backend' (focus on business logic, (persistent) state and interaction with other applications/machines). For front-end applications I've no real need for a number of things Django offers (ORM, authentication/authorization mostly). For building back-end applications Django has even more bits I do not really need. This lead to a situation where I asked myself 'what does Django still offer me? Is it not easier to use a more limited framework for either use case or gobble together my own frameworks from various bits and pieces?'. For front-end applications I could've (and have tried to) build a framework-to-fit from various bits and pieces such as cherrypy, jinja for templating, babel for i18n, routes for routing, etc. However creating a solid working framework this way, with all bits working together nicely - and keeping up to date with the development of its various bits and pieces - is a lot of work. Just using Django an ignoring the bits I don't need turned out to be far easier, leaving more time spending on my actual problem. And for building my backend-applications I don't need all the stuff listed above - I simply need a robust and reasonable fast networked server which can host my business logic. The 'minimalist' frameworks then offer just what I need without getting in the way too much. So in conclusion: if you want to build something that is mostly logic with a machine-machine interface, the minimalist frameworks offer a solid foundation and you have no real need for all the extras a 'mega framework' or even a 'middle ground framework' offers you. If you want to build something that has to interact with humans, you actually do need most of what the prevailing 'mega frameworks' offer you and leaving out the bits you don't want is easy. Hence there is no real need for 'middle ground' frameworks.
- cageface 14y agoHaving a compiler that will tell you all the places that you need to change things is an amazing productivity booster. Agree with this 100%. I think dynamically typed languages are a transitional technology we'll mostly leave behind as the kinks get worked out of modern type systems.
- grey-area 14y agoIt would have been interesting (and perhaps a little more convincing) to see some examples of the Haskell type system boosting productivity in such a dramatic way. I can count on one hand the number of type issues which have caused trouble for me in Ruby over > 5 years of producing complex systems with it. I haven't used Haskell though so would be interested to see some examples of this. If his audience is Ruby users, it is not very informative to just say it is better in a general way. The main point of comparison in the article point 1 seems to be with unit tests, however there are no concrete examples given of a failing test from a real program where types would have helped. A strong type system adds friction and verbosity, so it would need to come with a lot of advantages for me to prefer it to Ruby, which will not allow something like 2 + "2" but does try to get out of your way as much as possible. It's quite hard to compare type systems as they vary so much but at least here is he comparing just two systems Ruby/Haskell, so comparisons can be straightforward examples of situations where types have caused him trouble with direct comparisons. I'd be interested to see an example of something like a telephone number (from untrusted user input) where the Haskell type system is superior to having some checks on formatting, and an explanation for those less familiar with Haskell of what advantages the type system gives.
- cageface 14y agoI worked almost exclusively in Ruby and Python over the last ten years and coming back to static languages after that long was a real eye-opener. A good type system doesn't just help you catch a certain class of bugs. It completely changes the way you write code. Functions become self-documenting, aggressive refactoring becomes routine, the underlying architecture of your code emerges much more clearly. And you usually get much faster code for free. It's like having a genius savant pair partner. In my experience a good type system doesn't add much friction and the extra documentation you get from specifying types more than pays for itself in the long run.
- bfung 14y agoSome source code is worth a (three) thousand (fourteen) words ... =P
- batista 14y agoAnd a couple of finished products, well, web-apps or web-sites in this case, even more.
- deleted 14y ago[deleted]
- sandGorgon 14y agowhat issue are you referring to here ? Could you link to any relevant discussions.
- deleted 14y ago[deleted]
- danieldk 14y agoThe most common and impactful source of problems or bugs are ones of misconception, not TypeErrors, therefore anything that lets you iterate faster or get something out the door quicker is desirable. (I heard him say something to that effect in a talk) He must have a typechecker in his head ;). My experience with learning Clojure (knowing Haskell) is that I constantly bumped into bugs where I thought "Haskell's type checker would have caught this". Usually, when I write new functions in Haskell, I write down the type signatures first. This helps catching many errors. For instance, if your type signature is: f :: Integral n => [a] -> n You can not accidentally apply a function (in f) to f's argument that assumes a list of lists, or return something that is not an integral number. This cuts both ways: strongly encoding semantics using the type system catches many potential bugs in functions, but it also provides guarantees to the caller of a function. For instance, I know for sure that f does not return a 0/nil/None pointer, I know that the number is exact (since it is integral), etc.
- chc 14y agoDude, Clojure isn't even purely functional, nor is it meant to be. I respect Rich Hickey a lot too, but that doesn't mean he's some kind of god who blesses functional things. In reality, Haskell is much more at the forefront of functional programming than Clojure is — it actually embraces FP down to its core, purity and curried functions and all, while Clojure takes the more pragmatic stance of maintaining easy Java interop. Haskell's whole purpose is to push the boundaries of functional programming, while Clojure's purpose is to be a very useful modern Lisp that separates value and identity. Clojure is a really nice language and IMO more practical than Haskell in general, but it is not the last word on FP.
- vjeux 14y agoWhere are the benchmarks?
- DanWaterworth 14y agoHere http://shootout.alioth.debian.org/u32/which-programming-languages-are-fastest.php?ghc=on&jruby=on&yarv=on&calc=chart http://shootout.alioth.debian.org/u32/which-programming-lang...
- tikhonj 14y agoI think he wants the server benchmarks in particular rather than general speed. I found some on the Snap framework web site[1], but they may be a little out of date. [1]: http://snapframework.com/blog/2010/11/17/snap-0.3-benchmarks http://snapframework.com/blog/2010/11/17/snap-0.3-benchmarks
- danieldk 14y agoA slightly more recent benchmark: http://www.yesodweb.com/blog/2011/03/preliminary-warp-cross-language-benchmarks http://www.yesodweb.com/blog/2011/03/preliminary-warp-cross-... Also includes Yesod and Warp.
- DanWaterworth 14y agoLet's be clear, the article is comparison between frameworks. The benchmarks should therefore reflect the comparative speed of the same web application written using both rails and snap. I'm not aware of any attempt to do this, so I attempted to approximate it using the speed of the language in general and you can see that from the results I posted that the slowest Haskell GHC is faster than the 25% percentile of MRI ruby 1.9. This is a useful observation; A simple pong benchmark has absolutely no bearing whatsoever.
- joelthelion 14y agoThis one is probably more relevant: http://shootout.alioth.debian.org/u64q/which-programming-languages-are-fastest.php http://shootout.alioth.debian.org/u64q/which-programming-lan...
- danneu 14y agoI've been learning Haskell on the side for a while and was hoping for something more after reading the title, but the post pretty much just points out a few preferences that OP has. I spend very little time in Rails hung up on any of the issues expressed. With some experience with frameworks like Express/Noir/Sinatra, I find that Rails is productive for me because of (A) convention and (B) getting common things done with terse code like `belongs_to :forum, counter_cache: true, touch: true`, and (C) not having to write glue code for basic things. This quote... > In addition, there is also very little “convention” with Snap. It enforces nothing, which has the consequence (in addition to allowing you to make a mess!) of having the whole application conforming to exactly how you think it should be organized. ...is precisely the deal breaker for me. If OP thinks it's hard to add/edit Rails code because it's spread out, then a lack of convention suddenly isn't a very compelling scenario for productivity. At least you know where to look. I've been in a Node.js kick recently, consuming a lot of Express-stack repos on Github of smart people, and the experience is baffling. Deciding where to put code in my application just isn't a problem I want to solve when I'm trying to write a non-trivial, non-single-paged application.
- deleted 14y ago[deleted]
- carterschonwald 14y agoI'm slightly confused by this. Is it not the case with rails that many of the .rb files are generated via rails? I think you're over thinking / pessimizing what happens with haskell code. 1) for any self contained project (library or executable) in haskell, the directory structure determines the module names. if you're wondering how the functions imported from the Foo.Bar module are implemented you simply go to the subdir #root/Foo/Bar.hs 2) Types. when you're writing use case specific code, you are going to define use case specific types, and they will be declared. More over, it is good practice to give explicit type ascriptions to haskell code to make sure that it does in fact have the type you expect. This means that you can jump into a module and by also recursively looking at its imports (and you know where those are in the fs), you can figure out exactly whats going on. 3) cabal-install (cabal), and your project specific project.cabal file make life great. Why? the foo.cabal file will tell you which module has the Main function if you're making an executable, what other packages (and their versions) your code might be importing, which language extensions are enabled, etc. Point being, there are no need for "framework specific conventions" of the sort you're concerned about because those problems are solved by Haskell specific conventions :)
- delinka 14y agoOT: The title of this article without the parenthesized would be "...as productive than Ruby/Rails." Want a more link-baity title? Try "...more productive than Ruby/Rails?" making it a question. Not so baity, but with Moar English? "...at least as productive as..." This goes back to my little rant from last week: Please proof read your blog posts. In this case, reread the title with and without the parenthesized modifications and see if the English still holds together.
- nnethercote 14y agoThe single sentence that surprised me the most: "For performance, there is no question that Haskell will win hands down on any performance comparison".
- tikhonj 14y agoWhy is that surprising? Haskell is a compiled language with a very clever optimizing compiler, so it tends to be pretty fast by any standard. On top of this, it has recently had some improvements to its IO manager which is particularly important for web servers. Ruby, on the other hand, is notoriously slow.
- zoul 14y agoPerformance isn’t measured just by the language tools, it depends on the whole stack. It’s quite probable that the Ruby/Rails stack is better suited to high-performance sites simply because it has more installations and the kinks have been worked out.
- lincolnq 14y agoI agree that the priors would suggest that you are correct, however, let me give some evidence to update you: The Warp web server for Haskell is the fastest Web application server that exists. http://steve.vinoski.net/pdf/IC-Warp_a_Haskell_Web_Server.pdf http://steve.vinoski.net/pdf/IC-Warp_a_Haskell_Web_Server.pd... [pdf, but easy to read] -- in the comparison on page 2, php handled 3400 requests per second, and Warp 81000.
- danssig 14y agoNot a single line of code to illustrate the point? Not even one?
- mratzloff 14y agoI was coming in to write this. Rule #1 for these kinds of blog posts: include code samples! Sometimes I want to read long, detailed articles. Other times I just want to look at the "pretty pictures", so to speak.
- romaniv 14y agoWhen discussing structural issues, like routing, code samples will be either deceiving or extremely verbose, because the ideas like that involve interaction of multiple components that simply doesn't happen in "hello world" examples.
- mightybyte 14y agoYep, the same is true of the benefit static typing gives you for refactoring. Real world examples where the benefit is really significant are too big to put in a blog post. It should not require too much imagination to make the point clear to an experienced developer.
- islon 14y agotitle: "The Haskell / Snap ecosystem is as productive (or more) than Ruby/Rails." bio: "...computer programmer and web designer, who is interested in the intersection of mathematics and computer science..." Old stereotypes die hard.
- BadCRC 14y agoI really hope Haskell/Snap starts getting picked up by everyday web developers so someone can start exposing ridiculous things like: > 11111111111111111111111111111 - (length []) => 1729917383
- getsat 14y agoCan someone explain what is happening in this example? I'm learning Haskell right now and this makes no sense.
- mightybyte 14y agoIt's essentially the same thing as doing: > 11111111111111111111111111111 :: Int Numeric literals are automatically treated as Num instances, so when you subtract (length []) which is an Int, the literal is treated as an Int. In this case, it triggers an overflow condition, something that programmers understand well and have been dealing with from the earliest days.
- lincolnq 14y agoPrelude> :t 11111111111111111111111 11111111111111111111111 :: Num a => a Prelude> :t (length []) (length []) :: Int Prelude> 11111111111111111111111111111 - (length []) 1729917383 Prelude> 1111111111111111111111111111 - 0 1111111111111111111111111111 Prelude> 1111111111111111111111111111 - fromIntegral (length []) 1111111111111111111111111111 Prelude> 11111111111111111111111111111 :: Int 1729917383 "Int" is the machine-length integer type. "Integer" is the unbounded, but slower integer type ("bigint" in other languages). In Prelude, "length" always returns an Int, assuming that the length of a list will never be bigger than 232. Haskell interprets numeric literals as the typeclass (Num a => a), meaning any member of the typeclass Num can be constructed using these literals. Int is one such type, and causes wraparound when it constructs an instance using the typeclass.
- zopa 14y agoassuming that the length of a list will never be bigger than 232 Should be 2^32, of course. Though I think the real upper bound is (2^31)-1: there's a bit used for negative numbers, and there's zero.
- fusiongyro 14y agoLet's not downplay the few years you'll need to spend to get productive with Haskell first.
- vitomd 14y agoLearning Haskell will improve your overall programming skill, it will change your mind. The best tutorial to learn Haskell: http://learnyouahaskell.com/ http://learnyouahaskell.com/ .And it is the tutorial that I enjoy the most (including tutorials ruby, php, backbone, jquery, etc)
- VeejayRampay 14y agoMy language. It's better than your language. Ergo, you should use my language. Rinse and repeat with any choice of languages.