

Haskell web programming (a simple tutorial) - yogsototh
http://yannesposito.com/Scratch/en/blog/Yesod-tutorial-for-newbies/

======
mxavier
I'm having a hard time understanding the intent behind "You shouldn't need to
know Haskell". Do you mean in order to complete the tutorial and understand
what Yesod does? That's probably true. Being someone who's been studying and
using Haskell in personal projects for the past maybe 10 months or so,
Haskell's syntax and fundamental design decisions (while spot on, in my book)
are different enough from most programmers' skill sets that I don't think
they'll make it very far writing a non-trivial Yesod app without knowing
Haskell. I'm fairly proficient/enamored with Haskell now but I'm certain I
would have crashed and burned if I got my start trying to learn Haskell from
Yesod.

My first dose of Haskell was attempting to write an XMonad config. That turned
out to be a frustrating, several hour long ordeal for me that had me write off
Haskell as undecipherable, alien hieroglyphics for quite some time after that.
I'd urge anyone reading the tutorial who likes what they see to put in the
hard time to get a handle on the language, understand what its good for and
what it isn't and then return to web programming with it.

~~~
yogsototh
I am sorry if I didn't made it clearer. Of course, you don't need to know
Haskell to follow this tutorial in particular.

But it is clear in my mind, you must know Haskell to do something useful with
it. And in particular, make a web application, even if using a web framework.

As you stated, Haskell is not a language you could learn in 3 hours like I
learned the bases of Python. It takes a very long time to learn, particularly
when you're not used to functional programming.

But an intent of this tutorial was to promote Haskell. Clearly, if someone
want to do something a bit more useful, he will very soon realize he must
understand Haskell.

I added a specific advice in my conclusion similar to yours and pointing some
essential resources.

------
akg
Is there performance benchmark comparing Haskell and Erlang? I hear Erlang is
also quite performant when handling a large number of requests, but no hard
numbers. Are there similar web frameworks for Erlang as Yesod for Haskell?

Also, what about Clojure? That runs on the JVM but how does it fare on the
"correctness" claim of Haskell, i.e., "If it compiles it's close to what the
programmer intended".

I'm learning Haskell right now and really loving it. I wonder if I should
stick with it for more production projects or make a switch to Erlang/Clojure.
I know Erlang has quite a few success stories behind it, CouchDB being one of
them.

~~~
dons
I think it would be uncontroversial to say that optimized GHC Haskell
(statically typed, compiled, optimized, native code) is always faster than
current Erlang implementations (dynamically typed, interpreted, lightly
optimized).

For example, the fastest Erlang programs on the benchmarks game are all slower
than all the GHC Haskell programs,

* [http://shootout.alioth.debian.org/u64q/benchmark.php?test=al...](http://shootout.alioth.debian.org/u64q/benchmark.php?test=all&lang=ghc&lang2=erlang)

Median slowdown relative to GHC is 7x.

GHC is aiming for the high performance computing world of late, as well. The
Erlang language just doesn't have the facilities for raw number crunching
that's needed.

~~~
tete
Erlang is interpreted. Since this is not about a simple CGI application a
benchmark in which you compare the running time of a compiled executable with
the interpretation and running time a another program it doesn't make a lot of
sense.

Also this performance usually isn't the best way to argument about languages
for web applications. Often your bottleneck is somewhere else and i you really
have resource intensive stuff why not just interface C?

~~~
SomeOtherGuy
>Erlang is interpreted

No it isn't, it is compiled to bytecode and executed on a virtual machine,
just like most scripting languages are.

>Since this is not about a simple CGI application a benchmark in which you
compare the running time of a compiled executable with the interpretation and
running time a another program it doesn't make a lot of sense.

Read the site, this concern is explicitly addressed. The tests are long
running, not short tests repeated a million times. So the byte code
compilation step ends up too small to notice. That is why using a PHP bytecode
caching plugin doesn't increase PHP's performance on the shootout, and why
java isn't dead last from the massive startup time of the JVM.

>Also this performance usually isn't the best way to argument about languages
for web applications

This is a myth. Very few web applications actually have one CPU intensive
portion that can be moved out into a C module. Most web apps have pretty flat
profiles, where overall language speedups make the biggest difference. When
90% of your time is spent in 10% of the code, a C module is a reasonable
option. When 90% of your time is spent in 90% of your code, your only option
is a faster language.

------
prof_hobart
From the bit of Haskell I've managed to learn, it's a great language, and I
can see how an awful lot of the errors that you can make in other languages
will probably be avoided in Haskell, but I've never understood the (frequently
repeated) claim that

"If your program compile it will be very close to what the programmer
intended".

There's nothing I've seen in Haskell, or any other language, that will prevent
you implementing the wrong algorithm, or the wrong business rules etc. If
you're doing a phsyics simulator (to take an example I've played around with),
Haskell is not going to stop you badly miscalculating the gravitational effect
of multiple objects, or calculating the mass of an object incorrectly.

~~~
Peaker
That's the difference between an "intentional bug" and an "unintentional bug".

The former is when you want the program to do X, and X itself is wrong. Sure,
defending against this is rarely possible. The latter is in my experience far
more common. When you want the program to do X, but you actually told it to do
Y.

Haskell catches most of the latter cases.

One of the main reasons is the functional purity. Because return values are
the only result of a function, and these values are type-checked against a
specification, it is much harder to do the wrong thing.

For example, an imperative program will idiomatically have methods whose sole
effect is mutating their arguments or the objects. Even with a type system --
if you just omit the effects, the compiler really has no way to know that you
meant the effects to happen, and you will simply have a bug. A purely
functional program will idiomatically use a different style. Instead of
mutating arguments and objects, it will return a new value. If you forget to
return a new value, the compiler will catch that.

Additionally, the types in Haskell are generic by default. The more generic
the type of a function, the more _restricted_ is what that function can do.
The restrictions narrow the space of wrong things you can do.

Another interesting property of Haskell is where it chooses to be on the
"restrictiveness+guarantess vs. powerful+unguaranteed" trade-off.

It seems many don't even notice that the other side of the "power" coin is
"guarantees". The more powerful a construct is -- the less you can say about
what it will do. In Haskell, the purity and generic types of functions are two
things that heavily restrict code. But there are many other mechanisms to
_restrict_ rather than empower code. In many contexts, restrictiveness is
considered a bad thing, but in Haskell, this restrictiveness is very useful
for reasoning about code.

For example, the function of type: (forall a. a -> a) in Haskell can _only_ be
the identity function. It cannot print "hello world", and it cannot mutate
variables. These restrictions are useful because we now can have useful laws.
For example: id . f = f . id = f. And we can derive these useful laws from the
type itself, without even looking at the code!

By helping us find the most restrictive sub-language that can express the
solution, we rule out even more bugs.

~~~
rmcclellan
The power/guarantee trade off isn't a fundamental one, even though in current
languages you often have to choose between the two. Creating languages that
combine the power of untyped languages with the guarantees of static languages
is an active field of research. For example, dependently typed languages,
while currently too unwieldy for everyday use, show promise of having both
power and guarantees much stronger than Haskell. Now a third, ill-defined axis
of "usability" comes into play.

~~~
jerf
"The power/guarantee trade off isn't a fundamental one, even though in current
languages you often have to choose between the two."

It is on the Pareto frontier of the two. Which verges on tautological, but
it's still a useful observation. If you can trivially extend the power of a
construct while maintaining the same guarantees, the construct was simply
broken, and extending the guarantees of a construct without affecting its
power means simply that the guarantees were excessively conservative in the
first place.

(This can almost be copied and pasted any time anybody claims two properties
of a program aren't in conflict, the most common probably being security and
ease of programming.)

We may be wrong about where the frontier is... but I doubt we've _very_ wrong.

------
t-crayford
Spelling corrections, noted as I read:

"point of vue" -> point of view

"shell command are executed" -> "shell commands are executed"

"benchmark are here" -> "the benchmarks are here"

Also, heroku works just fine with haskell, as long as you compile a static
binary on an ubuntu machine. I compile mine on virtual box (via way of
vagrant), and have 3 haskell apps (none of them really production ready
though) running on heroku right now.

Lastly, I don't _really_ think haskell is the right language for a lot of web
programming. In haskell, you really want your logic to be as purely functional
as possible, but that gets pretty hard to do for web apps that rely on
external apis.

~~~
yogsototh
Thanks! Spell errors corrected!

When I said there is no heroku for Haskell it because it is not official.
Furthermore, do you have to use a 64bit architecture when compiling (just
curious)? I might try it myself.

And I even think that the argument against the number of Haskellers is in fact
a force instead of a drawback. It filter passionate people.

By external APIs, you mean that it would be difficult to write a simple
"connect to twitter/facebook" application? Could you tell us about any bad
experience you had?

~~~
t-crayford
Yeah, 64bit.

I never said anything about number of people...

External apis: nearly all the logic in my app leads to either talking to the
db, or calling an http api (and haskell can't use https apis _that_ well, you
have to use its bindings to libcurl). In general, it feels extremely difficult
to pull my logic out of IO (but maybe I'm just too dumb to).

It's not that its particularly difficult, it's just that it's not a problem I
think haskell is well suited to solve. I've used haskell to teach my self
automated logic proofs (just resolution refutation), compression algorithms
(huffman encoding and lz77), typechecking and breaking encryption (enigma).
Every time university exams roll around, I learning them on paper. It's by far
and away the best language I've used for stuff like that. It feels like web-
apps with lots of IO aren't really a problem haskell is well suited to solve.

------
jiggy2011
Is anyone here using haskell or a similar funtional language for any web app?

Would be interested in known your experiences and opinion compared to
something like django or rails.

How difficult is it to build something with a complex domain model?

~~~
SomeOtherGuy
>Is anyone here using haskell or a similar funtional language for any web app?

Yes.

>Would be interested in known your experiences and opinion compared to
something like django or rails.

Rails is an abomination, so pretty much anything would be better than that. We
rolled our own framework in scala. Despite initial resistance from some
dynamic language proponents here, it is now the only thing anyone here will
use for web development. Even the python fan won't touch django now.

>How difficult is it to build something with a complex domain model?

Easier than in dynamic languages. The problem with complex models is that
humans can't hold all that information in their heads. Static typing lets us
offload a bunch of important information to the compiler and have it error
check for us as we go. Our biggest issue has been that scala isn't strong
enough, I'd much prefer to be using haskell.

~~~
SkyMarshal
_> Our biggest issue has been that scala isn't strong enough, I'd much prefer
to be using haskell._

I hear that. I learned Haskell because I thought it would help me understand
Scala better (namely the type system), but Haskell spoiled me and I don't want
to use Scala anymore. Only thing keeping me on Scala atm is Lift, a truly
excellent rethinking of web frameworks. If I ever find the time I want to
start porting Lift to Haskell.

~~~
SomeOtherGuy
I'm not a huge fan of lift, but the portion of it I am ok with (the
templates/snippets side of things) is fairly similar to how you use snap. It
may be worth it to work on helping to finish snap (or forking it if need be)
rather than starting from scratch. Snap currently provides nothing for
database access, so you have a blank slate there to copy mapper or record from
lift (but those both suck horribly!).

~~~
SkyMarshal
Interesting, what aspects are you not a fan of (besides the persistence
parts)?

~~~
SomeOtherGuy
The model side of things is certainly my biggest complaint. The other things
are minor in comparison, but still annoying. I like the architecture of lift,
just not some of the details of the implementation.

I don't like the way templates are forced to use snippets to load data, in
particular as it results in snippets being dependent on the database, and thus
not suitable for unit testing. The framework should be pulling the data into
the view, which then passes it as an argument to the snippet to do whatever
transformation on it. That way snippets are entirely self-contained and easy
to unit-test. This is the sort of thing that I think would have ended up the
way I want had it been written in haskell instead of scala just because
writing small, self-contained functions is the typical haskell way of doing
things.

I hate the very opinionated nature of the form handling, and the even more
opinionated responses from the developers to questions like "how can I make a
form that works normally and doesn't require a session". People are not bad
for wanting forms to behave normally, and the "security" show the lift devs
put on to justify the form handling in lift is insulting.

While I find templates acceptable, they are seriously missing out on type
safety. I should get a compiler error if I create a template with invalid
html. Ocsigen got this part very right (an ocaml framework/appserver). Not
only do I not get this benefit for my markup, but lift itself generates
invalid html on me when using virtually any of the included form generation
methods. Very annoying.

Ideally what I want is a framework that gives me the type safety of yesod, but
with the structure of lift. I hate faux-mvc web frameworks and find they make
things more difficult rather than making things easier, and unfortunately
yesod copies the typical rails clone structure. Lift doesn't make the mistake
of trying to hide http from me, and gives me the simple and correct mapping of
template to url, leaves the domain model in the model instead of cramming it
into "controllers" that shouldn't be involved.

~~~
SkyMarshal
Thanks. Those haven't bothered me too much yet, but good to have on the radar.
That's the first real critique of Lift I've seen, other than 'it's not MVC'.

As for Yesod, I was also thinking it would be nice to have the type safety and
parallel/concurrent performance of Yesod with the templating and structure of
Lift. Don't know Yesod well enough yet though. Too many side projects.

------
gtani

        You shouldn’t need to know Haskell. 
    
        Don’t pay attention to all the syntax. 
    
        If you are curious you can take a look at Applicative Functor. 
    

This is a nice, whirlwind tour, maybe the opening benchmarks and jab at node
are superfluous. All haskell tutorials hit the speedbump of how to bootstrap
haskell understanding, where to make forward references and when to say "Trust
me" but code shown here: do blocks, ($), <\- and return would be confusing if
you didn't know _any_ haskell

~~~
yogsototh
Should I add a link to this article[^1] for people confused by the Haskell
syntax?

The opening is not really an attack. This is the way I myself started to be
interested in Haskell web programming.

[^1]: <http://blog.ezyang.com/2011/11/how-to-read-haskell/>

~~~
gtani
Yah, maybe just add links at bottom: LYAH, Applicative Functor wiki page. Or
maybe mention one syntax feature, IO's and do-blocks, and say "return" and
"<-" just kick things into and out of IO's, loosely speaking. Just don't say
IO's are like burritos ;-}

You could also say, for anybody that's looked at lisps, *ML, F#, scala,
erlang, the syntax isn't too bad, and for anybody that knows rails, they'll
recognize the same REST'y MVC layers/abstractions. I gather the target
audience is folks using dynamically typed languages.

------
agumonkey
Finally I know how to draw owls.

------
ericmoritz

      Haskell web frameworks handle parallel tasks perfectly. For example even better than node.js
    

of course, node.js has no parallelism

~~~
pjscott
I think what was meant was concurrency. Haskell's lightweight user-space
threading runtime is modeled after Erlang's.

------
minhajuddin
haven't finished reading the whole content, but the zoom in zoom out effects
are very annoying.

~~~
yogsototh
Are you talking about the zoom in when you click on some code block? I was
thinking to remove them.

~~~
minhajuddin
the Ctrl + , or Ctrl mouse scroll up or mouse scroll down

~~~
yogsototh
For me, it takes only one to two second animation. After it stabilize. You can
disable javascript and there won't be any CSS animation added.

~~~
Lewton
for me, in chrome, it takes 8-10 seconds to stabilize. and looks really wonky

~~~
yogsototh
I disabled animation for chrome.

~~~
tkahn6
Hey your site is really pretty. Would you mind licensing your CSS for personal
use? I'd like to use for my blog (which I will start one of these days).

Very nice blog post. After working on a Python stack during my part time job
(check out Apache libcloud), I can safely say that using a statically typed
language is a necessity for any non-trivial project. Without a type system you
offload the entire framework onto the programmer. To actually grok the project
you have to hold the complexity all in your head instead of using the types as
a guide and that makes getting started incredibly challenging.

~~~
yogsototh
Thanks.

The source code of my website is here:

<https://github.com/yogsototh/Scratch/>

And even if not clearly stated, everyone is free to use it and steal from it.
Of course, I'd appreciate to be mentioned.

If you want to have the full behavior you should copy not only the css but a
bit of js.

More precisely:

    
    
      output/Scratch/css
      output/Scratch/assets/css
      output/Scratch/js/init.js
      + jquery
    

You should have a functioning website which will be iPhone/iPod friendly.

You certainly also need to get the layouts:

    
    
      layout/article.html
      layout/default.html
    

Unfortunately, I didn't finished to switch to HTML5, the current code is XHTML
strict 1.0. You can have a preview of my HTML5 transition if you look at the
html5 branch. But I'll have to duplicate a lot of CSS modifications since.

If you want any more information, simply mail me, I'll be happy to help.

