
Haskell in Production: The good, the bad, and the ugly - hamidr
http://mwotton.github.com/hs_gbu/
======
tikhonj
I don't think the library situation is nearly as bad as some people--not
necessarily the author of this presentation--make out.

For one, Haskell actually has a pretty good and growing collection of
libraries, probably disproportionate to the language's popularity. Web
development, in particular, is well represented: there are several competing
web frameworks; Yesod even has commercial backing now. Haskell even has some
libraries that are not well reproduced in other languages like QuickCheck and
Parsec. I've also been looking at sbv lately, which seems rather more
convenient than other languages' alternatives.

Additionally, libraries aren't the only thing that matters. In fact, most
libraries are pretty trivial. I remember seeing a presentation by Brian
O'Sullivan online about his experiences with using Haskell at a startup. One
point that really stood out to me was about libraries: sure, some libraries
(like JSON parsing, I believe) were missing; however, it only took him
something like a couple of days to write it from scratch. Those days are
easily overshadowed by Haskell's core advantages. I would much rather spend a
couple of days writing a new library than trying to track down a bug Haskell's
type system would have caught. The beauty of this system is also that each
library only needs to be written once and can then be reused, making the world
better for everyone.

Now, there are some other issues with Haskell. Cabal really is a big one. I
just spent quite a while fighting cabal, and I'm not even sure how I won in
the end :P. Happily, I believe people are working on addressing the cabal
issue.

I'm sure there are other annoyances besides. But no language is entirely free
of annoyances. Considering everything, I really do think Haskell is a good
choice for a very wide range of programming problems, especially in a startup
setting.

~~~
Argorak
I find the linked slideset uninteresting, as it misses the speakers words -
its just a collection of positive and negative words. Still, I want to reply
to your comment, even if my reply is bit harsh, but Haskell always makes me a
bit bitter:

First of all, I played with some web frameworks in Haskell and didn't like
them at all: the yesod community had a very dismissive tone towards people
that didn't want to use what they perceived as "standard" and Snap is well
organized, but sometimes weirdly implemented around the corners (WAT? The
templating library also serves static files?). I would love to use any of
them, but they are still not fit to build ecosystems like Django, Rails or
Spring.

Its nice that you picked the JSON library (by Brian?) as an example for a lib
that can be written in "a few day". `aeson` is a great library. Its just not
something that someone without detailed Haskell knowledge can write in a few
days. It requires good knowledge of Haskell, especially things like the
GHC.Generics library and Template Haskell (Hint: GHC.Generics is not very well
documented for practical uses as well, the documentation spares you of the
hard cases).

I found that if you go away from those 'core' libraries, quality drops
sharply. Giving just one example may be unfair, but I do it anyways: the
readline bindings (haskeline) didn't build on OS X for 2 major releases
straight. Also 0.1 and 0.2 seem to be very common version numbers on hackage
and most documentation boils down to type descriptions. For loves sake, I
couldn't find a good and proper tutorial working with bidirectional streams
(think websockets) and asking a GHC committer ended in "well, we're still not
sure what the best abstraction for this is, theres multiple competing" and
someone on the Haskell User Group Berlin said "well, its not such an easy
problem, but it will be solved in a year or so". In Ruby, thats implemented in
an hour (safe and sound using libraries, with proper abstractions), today.
Yes, I honestly think that the library situation is bad - its not the lack of
libraries, its the number of half-hearted libraries vs. the real good ones.

Also: Pro-active teaching, like producing screencasts and tutorials is sadly
not very common in the Haskell community as well (weirdly, this is spotty:
haskell-cafe, Real World Haskell and Learn you a Haskell are shining examples
of how things should be, also in other communities).

I am surprised by how much the Haskell community always says "type system"
first, but seems to put all other practical considerations on the backseat.
Also, it is common to just dismiss concerns without addressing them.

That said, I still love Haskell and enjoy developing in it when things are
working smoothly, I just wished that the community were more receptive and
less dismissive to actual problems of people that are not as deep inside the
language as people spending every evening on it.

~~~
batgaijin
Before my rant: I think the Haskell community is incredibly nice. It is the
most helpful and brilliant group of people I have interacted with in my life.

Rant:

Yes, I have spent a while getting up to speed with Haskell. I think it has
definitely made me a better programmer to learn, but I really don't like how
quickly everything seems to go in the deep end.

The need for the 'right' abstraction and 'good enough' stuff like Cabal really
irritates me. Cabal is especially hurtful to the community growing. I think
there needs to be a much bigger investment in Nix, that is an absolutely
amazing project that barely gets the attention it deserves.

Another thing that really makes me not want to invest time in Haskell is how
quickly code starts to depend on language addons. I think that idea can be
done well, like in Racket, but for Haskell it really seems like a scary way of
bandaging the standard.

~~~
merijnv
What do you mean by bandaging the standard? And why are extensions scary?

In general none of the extensions change the behaviour of valid "standard
haskell" (beyond adding a small handfull of new keywords, rendering those
words illegal as variable names). So calling it "bandaging the standard" seems
a bit harsh/odd.

I think extensions are a nice way of keeping the language moving forward
without being slowed down by the standardisation process. The standard can
then catch up in its own time.

~~~
Argorak
Because there is no better way of saying "this is not finished yet and might
be removed at any time".

------
comex
I don't even know Ruby, but it's clear that the idea that Ruby is an
"amazingly primitive" language that people are using instead of Haskell
because it has existing libraries and services or because "startups are not
technical" is drastically wrong and almost insulting. To the contrary, Ruby,
probably more than any other language, has a large community that's highly
enthusiastic about its programming style and culture, which is the reason most
of those libraries and ecosystems were created in the first place. I know this
is just a few bullet points, but vaguely mentioning a few (good) reasons to
evangelize Haskell (plus a motorcycle) along with three seemingly random
relatively small issues as criticisms of Ruby (plus a horse and wagon)
distorts reality almost to the point of unrecognizability.

~~~
regularfry
Compared to GHC, MRI really _is_ primitive. Parts of this are intentional: the
object model is intentionally simple, and one of the design goals was to keep
unixy goodness close to the surface, so the IO model, forking and so on are
quite shallow shim layers over the system calls.

Other parts, like the threading, the GC, and the parser (oh god, the parser)
are suffering from baggage that's never had GHC-levels of academic effort
thrown at it.

    
    
        To the contrary, Ruby, probably more than any other language, has a large community
        that's highly enthusiastic about its programming style and culture, which is the reason 
        most of those libraries and ecosystems were created in the first place. I know this is just
        a few bullet points, but vaguely mentioning a few (good) reasons to evangelize Haskell 
        (plus a motorcycle) along with three seemingly random relatively small issues as 
        criticisms of Ruby (plus a horse and wagon) distorts reality almost to the point of    
        unrecognizability
    

The presentation is making the point that MRI _itself_ is primitive, and
addresses the plus points of the community in the very next slide. For people
who care about the implementation underlying their code as much as they care
about their own code (or more), MRI's shortcomings are a visible downside.

------
shin_lao
Although I'm mainly a C++ developer, I'm a big fan of functional programming
languages.

Haskell is more difficult, it requires to really grasp some computer science
principles whereas you can start hacking php/python/ruby right away. It
requires to _actually think about what you're going_ to do instead of
integrating a couple of libraries: that's a double edged sword.

You need to understand that the added value of Haskell for most start ups is
near zero. It will more difficult to hire, the final result will not be better
and in the end code quality matters less than business relevance.

If your technical founder is a Haskell guru and knows a couple of engineers,
then sure, why not, it may provide some competitive advantage, otherwise just
forget about it.

~~~
danieldk
_You need to understand that the added value of Haskell for most start ups is
near zero._

I used to have that opinion as well, but I am slowly retracting it. Very
strong typing and great abstraction does make development easier. E.g., I have
been writing parsers lately for an application-specific macro language.
Writing such parsers using a good Haskell parser combinator library such as
parsec is many times more productive than parser generators for most
imperative languages.

Another advantage is that strong languages allow you to refactor code easily.
If you change some types, the compiler will find type mismatches, allowing you
to fix code rapidly. I can imagine that startups often refactor and
substantially modify their codebase.

In the end you do not only want to develop an application quickly, but also
correctly. If a strong language can be used to eliminate most errors and
improve productivity, I see it as an asset to a startup.

~~~
shin_lao
You have tools to help you find mismatches in Python. I agree that maintaining
a large code base in Python (or Ruby) is harder, but it's possible and is
mainly a question of discipline and process.

 _If a strong language can be used to eliminate most errors and improve
productivity, I see it as an asset to a startup._

Most startups projects I've seen are technically trivial.

~~~
chii
> Most startups projects I've seen are technically trivial.

may be this is due to the fact that technically non-trivial problems aren't
easily solved by startups, who might tend to choose a technology thats easy to
use (such as php/ruby), but makes it difficult to solve the technically non-
trivial problems with the same degree of ease?

I m just guessing here having no real insight.

------
hamidr
Ask HN: Anyone using Haskell in production?
<http://news.ycombinator.com/item?id=1909093>

------
nnq
...I know that HN people are mostly *NIX oriented or dislike Microsoft
technologies ...but how about F#? ...wouldn't it provide most of the
advantages of a ML family language but coupled with the "smoothness" of VS
tooling and .Net integration that could take some of the deployment pains away
and provide the "accelerated liftoff" needed by startups?

(It's a question, not suggestion... I must admit I've never had the balls to
use ML of Lisp like languages in production so far...)

~~~
ryanpers
well, you got it in the first paragraph - because Windows isnt Unix, and
people dont use it for production. F# is in theory nice, but devops'ing
windows, I just dunno man.

~~~
nnq
I've heard there's also good F# support via Mono now (but then again, I dunno
about devops'ing with Mono... I wish someone had the balls try this and post
about the experience...)

~~~
MichaelGG
I've been deploying F# into production for a couple years, on to both Windows
and Linux. They're rather simple daemons that talk to databases, message
queues and filesystems, and do telecom logic (routing/billing).

Overall, Mono has been incredibly smooth. I prefer to compile from source as
RedHat doesn't come with packages for mono. That takes time, but isn't a big
deal. F# support seems lacking when it comes to some of the tooling
(compiling, interactive).

mono-service, the service daemon to act like a Windows Service host (allowing
same code as on Windows, and ~5 lines to a minimal daemon) sometimes has acted
weird, but it's been due to how it handles it's runfiles and lockfiles, and
once you know that it's easy enough to make sure they're ok. (As in, if one
user ran it, the perms are wrong so another user can't even check it, and the
error messages aren't there/clear.)

F# performance is on par for .NET. If a certain high-level feature is not
generating great code, there's always the option to drop down or approach
another way. F#'s much more flexible than C# when it comes to performance.

F#'s why I stay on the MS stack. .NET is pretty compelling with it's base
library and great tool/developer support. But after seeing powerful languages,
I just get so annoyed with the verbosity of things like C#.

~~~
mattmanser
Verbosity in C# practically disappeared with 3.0, released with .Net 3.5.

There are a couple of things left that annoy me, but mostly it's gone.

~~~
MichaelGG
It got _better_, way better, much nicer than Java. It's not even remotely
gone. Type inference is crap in C#, and they even admitted in some cases, it
was due to compiler design problems, not language design[1].

Even local vars can't be type inferred if they're functions, because of C#'s
confusing decision to use the same syntax for lambdas and quoted code.

The ASP.NET MVC team resorted to using reflection on anonymous types, because
there was no lightweight way to pass in a set of options at runtime. With a
more expressive syntax, that'd be needless.

C# has statements that aren't expressions, which really bulks up code and adds
flow for no reason. In F#, even "if" and "try" blocks are expressions which
again keeps slimming things down, and more importantly, keeps the code
simpler.

In one direct "line-by-line" translation (C#->F#), F# reduced the number type
annotations I needed by 95% (1/20th).

No pattern matching (and thus no active patterns!), little type inference, no
syntax for tuples, no lightweight function syntax, no code nesting, no
workflows, (and a weird hardcoded one just for async), no top-level functions,
no custom operators, and C# is flat-out downright clunky when compared to F#.

It may be one of those "you don't know what you'll miss until it's gone" kind
of deals. I've used C# now and then, even last month on an entire project, and
it just feels tiring.

1:
[http://blogs.msdn.com/b/ericlippert/archive/2009/01/26/why-n...](http://blogs.msdn.com/b/ericlippert/archive/2009/01/26/why-
no-var-on-fields.aspx)

~~~
psionski
+1. Your story sounds a bit like mine a that guy's -
[http://lukeplant.me.uk/blog/posts/why-learning-haskell-
pytho...](http://lukeplant.me.uk/blog/posts/why-learning-haskell-python-makes-
you-a-worse-programmer/) :) It's a bit old, so some things don't apply
anymore, but still.

------
forgotusername
I've no doubt this presentation makes some interesting points, but I'm as
inclined to finish reading it after noticing it's destroying my browser
history as I would continue evaluating software after noticing it's randomly
corrupting my home directory.

Please leave history alone or at least use window.history.replaceState().

~~~
regularfry
Also a bloody pain to read on a mobile device.

~~~
lmm
It's not exactly easy to read on a desktop either.

------
klibertp
"strong _static_ types save time"

I would find the presentation without controversial points at all were it not
for this one sentence :)

Edit: aaargh, I treated mention of Ruby primitivism as a joke and forgot about
it; if taken seriously it can be controversial as well.

~~~
rpearl
every single NoneType error I have gotten using in the python I'm paid to
write would go away with a static type system.

Every single function I've changed the signature of and then failed to change
one caller would go away with a static type system.

I cannot count the number of times I've had to stop and write down the types
of things I wanted to reason about, an d then keep all that in my head, to
figure out what was going on in a large code base. Guess what? Most of the
types were static. If I had Haskell's good type inference, I wouldn't have had
to do any of this time-wasting endeavor.

The statement isn't controversial. Correct code type-checks. When there are
type errors in your code, in a dynamic language, they would be bugs found at
runtime.

[edit for formatting]

~~~
cdavid
Dynamically typed languages are used everyday to write robust software
(erlang, lisp, etc...).

You're making a common mistake, which is to reason about static typing
advantages _everything else being equal_. Sure, if static typing had no
drawbacks, it would be insane for any language not to be statically typed, for
some of the reasons you're giving (and others). But everything is not equal.
Static typing is a tradeoff, and lots of its advantages are often caused by
something else (or in combination with something else). Don't get me wrong,
Haskell is an impressive feat (just starting learning it), but in haskell,
typing is associated to advanced type inference, purity, etc...

In my experience being paid to to write python, a lots of NoneType, attribute
errors, etc... often have a deeper underlying reason linked to bad
architecture, and bad programming practices. I am not convinced typing would
make improving those projects easier (certainly, a primitive typing system ala
c/c++/java does not in my experience).

~~~
to3m
Type error: "everyday" is an adjective, adverb expected in this context ;)

The examples you cite would be detected by a type checker. The attribute
errors wouldn't even need a complicated one. (I've never had an attribute
error in C.) It's fine to complain that these things are due to bad
architecture, in whatever way that might be, but if there were a type checker
involved then the code wouldn't even build if there were a type problem. It's
fine to rail against poor design, or systems that are hard to use for no good
reason, but in the mean time the code usually has to actually work.

(And if there were no type problems, it would run fine without one, bad
architecture or no.)

------
arocks
Ah, powerpoint presentations where the truth is somewhere between the bullet
points. I would have preferred a blog post which gives the author enough
breathing space to justify his claims.

Haskell's single biggest problem is that it looks unfamiliar to programmers
who are trained in traditional imperative languages. Due to its minimal
syntax, its error messages can be confusing to a learner. New languages like
Scala and Clojure are packaging many of Haskell's concepts in a more familiar
syntax. They are gaining popularity since they actually solve hard problems
like concurrency.

In my opinion, startups prefer Ruby because they prefer to start solving the
problem right away without worrying too much about its correctness. A classic
case of "Worse is better" works for most web applications. Whereas, Haskell
requires some thinking into how to best model the solution before you start
implementing it. This often leads to more 'correct' code.

~~~
prof_hobart
I think that one of its biggest problems has been the vast majority of the
"Teach Yourself Haskell" books/articles.

When I first had a go at learning it, I ran into two common problems with
them. Firstly they usually did a great job of showing you how to write a
quicksort or a Fibonacci sequence but then struggled to explain how it applied
to most every day challenges (things like i/o - and yes, I sort of understand
the complexity around that in Haskell, but as a developer, it's one of the key
things I'm likely to want to do).

The other problem was that examples were typically full of what I would
consider appallingly named/abbreviated functions,parameters etc

"fib' (f, g) p"

for example.

When you're already struggling to understand langauge concepts, having your
code full of "f,g, and p" and trying to remember what they mean really doesn't
help.

I think it's improving (Learn You a Haskell looks pretty good, but I've not
had a serious attempt to re-learn since that appeared), but it's always been a
bit of stumbling block for me in the past.

~~~
dbaupp
> The other problem was that examples were typically full of what I would
> consider appallingly named/abbreviated functions,parameters etc

As adimitrov points out, this is in many ways a carry over from mathematics.
However, this isn't the only factor.

For the parameters:

Expressions and functions in general are usually much shorter in Haskell than
in other languages, so one can see _how_ the variable is being used, e.g. the
conventional definition of map is:

    
    
      map f [] = []
      map f (x:xs) = f x : map f xs
    

One can tell that f is a function and that it's doing something to the first
element of second argument, and then recurring on the rest of that list. That
is much much nice, than (at worst)

    
    
      map function list = if null list then [] else ((function (head list)):map function (tail list))
    

Secondly, the types tell a lot about a function and it's parameters, for the
above

    
    
      map :: (a -> b) -> [a] -> [b]
    

one can easily see that the first argument is a function and the second is a
list, and the specific types mean that there is a single sensible way to
combine them: apply the function to every element of the list.

(Lastly, there are conventions, which take a little time to learn, but they
help. E.g. f, g, h for parameters which are functions, (x:xs), (y:ys) for
head/tails of lists.)

However, naming the functions poorly is a problem. (But type do help with this
too, especially with Hoogle[1].)

[1]: <http://haskell.org/hoogle>

~~~
prof_hobart
The x:xs one is fine as long as it's properly explained in the tutorial - e.g.
it's a list of items, with x being the first item and xs being all other items
in the list.

The

map :: (a -> b) -> [a] -> [b]

may well be abundantly clear once you understand Haskell's types, but is
rather less so when you're first learning. In that particular case, I'm not
entirely sure I could come up with a clearer set of names, but there's plenty
of times when I was first learning that I really struggled with getting to
grips with a concept simply because the naming left me wondering why I was
passing an A into a Q to get a list of Zs (or whatever it was).

~~~
wonderzombie
I'm not sure how specific to Haskell this actually is, though. Think of
templates in C++ (esp. template functions) or generics in Java. You use T or
whatever as a placeholder for actual types. Any time you need more than one
type, you're forced to make a similar decision about how to describe a type
about which you know very little.

It's is a heck of a lot more concise than either of those, though. Might this
be the actual stumbling block? You're _saying_ a lot about map -- in a very
precise way, mind you -- without _writing_ a lot.

~~~
prof_hobart
C++ templates and generics are relatively advanced features though. I wouldn't
be expecting to teach them in lesson 2 of the langauge.

And what you would call a parameter in a production app is not necessarily the
same you'd call it in a tutorial.

------
cabalamat
Does anyone really think that a slide presentation is a better way of saying
what the author wanted to say than an essay?

And if so, do they also think that Norvig's Gettysburg Powerpoint Presentation
is better than Lincoln's Gettysburg Address?

------
peterjs
What does CoW mean? As in "GC breaks CoW & caching". There are quite a few
acronyms and supposedly even some animal with these three letters.

~~~
mwotton
Copy-on-write.

------
Bjoern
Is this a slideshow? I can't do anything here in FF 16.0.1.

~~~
bazzargh
Ditto. I just turned off page styles and read the text. There's not much of
it.

------
beering
What about virthualenv (virtualenv for Haskell)? Does that help alleviate some
of the cabal issues?

~~~
boothead
It worked well for me, and there's cabal-dev too. BTW, I think virthualenv is
now called hsenv.

------
Qerub
I'll consider Haskell for serious programming when (and if) it gets a decent
record system.

[http://bloggablea.wordpress.com/2007/04/24/haskell-
records-c...](http://bloggablea.wordpress.com/2007/04/24/haskell-records-
considered-grungy/)

~~~
nandemo
That blog post seems fairly outdated. There are several lenses libraries that
provide decent record support:

[http://stackoverflow.com/questions/5767129/lenses-
fclabels-d...](http://stackoverflow.com/questions/5767129/lenses-fclabels-
data-accessor-which-library-for-structure-access-and-mutatio)

Personally, I'd much rather have a better baked-in record system, but that's
unlikely to change substantially now.

~~~
applicative
The state of the art is the amazing `lens` package
<https://github.com/ekmett/lens/wiki/Overview> . See this example,
<https://github.com/ekmett/lens/blob/master/examples/Pong.hs>

~~~
Qerub
Looks great! I hope it gets more broadly adopted. Thanks for sharing.

------
ryanpers
"startups arent technical"

I guess YOUR startup isnt technical... But there are in fact technical
startups out there. It's just that they make more money than yours, do better
and are generally cooler.

~~~
mwotton
My startup involved custom hardware and realtime messaging. I still would have
been better off in the early stages writing it in Ruby.

------
_pferreir_
> Ruby is amazingly primitive

What? In what sense in Ruby primitive?

~~~
wladimir
"primitive" is an awkwardly chosen word with negative connotations... I
suppose it is in the sense that it doesn't do type inference (or reasoning
about types at all, for that matter). Like a Lisp it simply executes what you
write without any validation beyond syntax checking.

The idea is that Haskell's type-based, lazy approach allows for a more high-
level approach of specifying what you want instead of how you want it
executed. I'm not sure it always succeeds in that, but that's another matter.
It's an interesting language nevertheless, with elegant code, but if I need to
build something quickly I fall back to Python (which is "primitive" in the
same sense as Ruby).

~~~
draven
> Like a Lisp it simply executes what you write without any validation beyond
> syntax checking

But then in Common Lisp when something goes wrong you drop into the debugger
and can look at your code's state. In python/ruby my program just goes poof!
and I get a backtrace. Then I'll either have to add statements around the
suspected cause of the bug to inspect the environment or restart with a
debugger and retrigger the bug.

The Common Lisp Way(tm) is also available in Smalltalk; I think those systems
give you the tools to deal with their dynamic nature, while python and ruby
(and others as well) do not.

And then languages with more static type systems can give you the tools to
deal with their static nature. In Haskell that would be powerful type
inference and expressive type system.

~~~
wladimir
Well, dropping to the interactive prompt is a statement or two in Python. You
could do that when something goes wrong (for example, in the inner, or outer
exception handler of your application).

There's also tools for Python where you can browse/modify state of a program
remotely through a debugger, for example winpdb, others included in IDEs.

Overall, dynamic debugging support is quite good, if you are willing to search
around a bit. But probably not as good as CL or SmallTalk, if they're
especially engineered for these kind of things. I don't know enough about them
to comment on that.

------
thu
I think it is very positive. I read it as "Things are being done, please be
patient. B.t.w. what's done is insanely great".

------
finnw

        * $LANGUAGE is amazingly primitive
        * GC breaks CoW & caching
        * dynamic -> lexical scoping between $OLD_VERSION & $NEW_VERSION
        * concurrent behaviour requires event-driven style
    

Exactly the same could have been written about Lisp in the late 80s

------
the1
eh? haskell program can be really slow, especially when it is written by non-
experts who don't understand lazy evaluation well.

~~~
Deestan
A _< Language>_ program can be really slow, especially when it's written by
non-experts who don't understand _< CorePrinciple>_ well.

------
Supreme
This is a terrible set of slides. The only new thing I gathered from it is
"cabal sucks". Then the presentation came to a sudden end which left me
thinking "what, that's it?" How does such a low quality link get so many
upvotes? _takes notes for future marketing endeavours_

~~~
mwotton
It wasn't really intended to make much sense by itself. I find if I make
slides that stand alone, the audience reads the slides and ignores me. I put
the slides up as a courtesy to the people in the audience.

There was less than zero marketing involved - I gave this talk months ago and
only just noticed this thread.

~~~
Supreme
Apologies if I sounded like I was criticising what you do - I'm sure that
these made a lot more sense in the context of a presentation. I was
questioning why the person who posted this link did so and why it has been
upvoted to such an extent.

~~~
mwotton
not caremad, just clarifying. I'm as baffled as you are.

