views:

1309

answers:

12

I've been an OO/procedural guy my whole career except in school where I did a lot of logic programming (Prolog). I work on an amazing variety of projects (freelancer) and so I don't want the tools I know and understand to hold me back from using the right tool for the job. I've decided I should know a functional programming language.

I've narrowed the field to Haskell and Erlang. What are the pros and cons, advantages and disadvantages, and major trade offs of Haskell and Erlang? How do I decide in a rational way, which is the better path? This is a big time investment, so I'd like to chose wisely.

Is there a good case to be made for something else entirely? F#, Scala OCaml?

(BTW, I'm normally a Ruby/C/Obj.C guy, so I'm not terribly impressed or dependent on the JVM as a runtime. It's completely neutral to me. It's a fine runtime, I don't hold it for or against a language. I don't use Microsoft products though, so a .NET runtime would be a negative.)

UPDATE: Thanks for all the great feedback! After reading all the answers here, and thinking about it for awhile, and checking out the excellent Try Haskell and Try Erlang, I've decided to learn Erlang. Both seem like fantastic options, but as an old Prolog guy, the Erlang syntax seems more logical and readable and less foreign to me. I'm also pretty excited about Erlang's message based concurrency versus Haskell's transactional memory. As on OO guy, messaging just makes a lot of sense to me. Wish me luck!

+12  A: 

If you want to build actual stuff, id go for Erlang. It has a decent amount of libraries and is mature and proven to work good in a production setting. Its built for zero-downtime concurrent systems.

If you mainly want to learn functional programming (and type-theory) then go with Haskell.

Both languages are designed well, and anyone would benefit from knowing both.

johanbev
I very much want to build actual stuff. This isn't about rounding out my knowledgebase so much as it is about being able to recognize when an FP approach is the "right" one, and then use FP to get stuff built and get crap done better and faster.
Sean Johnson
The jump from "It's built for zero-downtime concurrent systems" to "If you want to build actual stuff, use it" seems like a non sequitur. All that seems to show is that it's good for zero-downtime concurrent systems. I also question the implication that Erlang has better library support. Haskell has the Hackage repository with thousands of libraries and the Cabal package manager. Erlang appears to have a couple of libraries on various people's homepages.
Chuck
Haskell's Hackage has just on double the number of libraries as Erlang's library site, by the way.
Don Stewart
@Chuck and Don. Notice I say nothing about the libs of Haskell, and just proclaim the libs of Erlang decent. (not good, not horrible). My intent was to say that (IMO) Erlang is the most production/industry oriented one of the two, but Haskell is probably the most interesting from a theoretic/personal improvement point of view.
johanbev
I don't really see any evidence that Erlang is particularly more "production-oriented" outside of its particular niche. If you're writing a telephone system, sure, Erlang is tops. But I don't see how that translates to "If you want to build actual stuff, go for Erlang." You just seem to be making an unjustified leap. If not, a little more explanation of how it's better suited would be helpful.
Chuck
@johanbev is too modest, as usual. He's been part of three very successful startups (Bluetail, Tail-F and Klarna), all based on systems written entirely in Erlang and whose main advantages were a combination of robustness and very short time to market. (Klarna is one of the fastest expanding companies in Sweden, currently employing some 200 people.) @Chuck didn't know this, of course, but if there's someone who isn't making an unjustified leap here it's johanbev. Erlang's main niche is not just telephone systems - it's all kinds of network, communication, and control systems.
RichardC
@RichardC, I think you have me confused with another Johan (bev), but still thanks for the stories, maybe we can get the johanbev between these systems to comment as well.
johanbev
@johanbev sorry for the confusion - I was convinced there could only be one Erlang-related person with that signature. The gist of the story is still valid, though.
RichardC
+14  A: 

Haskell is a statically-typed, general-purpose purely functional language. It has the most powerful static type-system I know and forces you to program functionally. Its syntax is extremely concise and no side-effects are allowed without the type system noticing it.

You definitely get the best overview over functional techniques here (including lazy evaluation, monads, ...), but I can't promise it's the most productive tool for an actual job.

Erlang (and Clojure) is mainly built for parallel-processing and distributed computing (telecommunications, websites). They're dynamically typed and have high-level concurrency structures built-in (e.g. Actor model).

F# is impure - You can programm functionally if you want. It targets .NET, which it's fully interoperable with (as Scala with JVM/.NET). Its type system is quite advanced (but not as advanced as Haskell's) - It might be the most productive language for general-purpose applications here.

Dario
I for one will promise that Haskell makes you extraordinarily productive.
Apocalisp
You emphasize _purely functional_ as if the other languages were _somewhat dysfunctional_.
jetxee
@jetxee: All languages are dysfunctional, but some are more dysfunctional than others...
camccann
@jetxee: No (I actually suggest impure languages can be more productive for general-purpose cases), but I consider purely functional languages (especially in combination with a type system like Haskell's) a very interesting and important concept. Since this question is (partially) about learning something absolutely new, purely functional languages have to be explicitly emphasized because it's the most extreme variant of the underlying philisophy.
Dario
Clojure has no distribution at all.
I GIVE TERRIBLE ADVICE
+8  A: 

Haskell is the definitive functional language, given the attention it receives from the academic community. There will always be something interesting and cutting edge going on in the development of Haskell. It's also purely functional language by default (Erlang and the others you mention are not).

If you really want to dive into functional languages, and you're already used to Ruby or C, I'd recommend Haskell.

Edit: since you mention "building real stuff", the following article might be useful:

Haskell in Industry

Will
Isn't Erlang purely functional too? As I know, there is no variable change allowed [and the *the type system has to notice change*-definition is not applicable due to it's dynamic type system].
Dario
I don't think it is purely functional due to the message passing, which is technically a side effect.
samoz
That was poor editing on my part - changed!
Will
@samoz is right. Functions in erlang are definitely not referentially transparent, so you can't call it purely functional.
sepp2k
I'm going to pretend I was right the first time, but I had to look it up. Erlang isn't purely functional by default in the same sense that Haskell is.
Will
+3  A: 

Haskell teaches you a lot and gives you a totally different perspective on programming. It's really worth learning, not for being able to write Haskell programs, but for improving your programming and reasoning skills in general.

Erlang gives you less of this (still quite a bit), but for that is definitely a "real-world" language.

I would suggest at least learning the theory of Haskell (types, type inference, monads, laziness), if you don't wish to become proficient in Haskell programming.

Artelius
+3  A: 

Erlang is impressive if you have a high-volume application that needs to do parallel computations. The Erlang VM is second-to-none in this respect. The ability to do huge amount of multitasking seems amazing, but then when you get into the self-correcting abilities Erlang has, you will be even more impressed.

[Shameless Plug] I have a few entries in my blog about the Erlang VM and Erlang in general. Link in profile [/Shameless Plug]

I vote for Erlang.

samoz
+12  A: 

Simon Peyton Jones (a founding figure in Haskell) gave a great talk entitled "Haskell and Erlang: growing up together" at the Erlang Factory meeting in 2009. There is video too. The presentation is remarkably balanced, discussing the different roads taken.

leander
That sounds like a great presentation. I'll be checking it out.
Sean Johnson
+30  A: 

My unsupported and semi-informed opinion: Some mixture of Haskell, Erlang, and Clojure represents "the future" of programming languages. Not necessarily any of those languages themselves, but something inspired by what they've done. So really, you can't go wrong with those, I think.

In more concrete terms, I like Dario's answer, but I'll speak to a few practical details about Haskell:

  • Haskell is a very expressive language with a steep learning curve. Unless you're coming from an ML background, expect it to take three times as long to become proficient with Haskell as with most other languages.

  • Haskell currently has a very active and helpful community (e.g., compare the haskell tag on Stack Overflow to other functional languages). It's nice to not be alone in the world. Not to say that other languages don't have active communities--I just don't know--but Haskell definitely does.

  • Much is made of Haskell's purity, but that's a distraction at best. The important thing about Haskell is the type system as a whole. In most static-typed languages the type system just gets in the way; in Haskell, the type system is expressive enough that you can encode non-trivial guarantees about the program logic[0], thereby turning many classes of bugs into compiler errors. Constraining side-effects is an important, but over-hyped, subset of this.

  • Haskell is very flexible with syntax and type constraints--not quite to the extent of a Lisp dialect, but it still makes an excellent "host language" for embedding domain-specific languages. Haskell also has at least three extant forms of metaprogramming support[1], which is both a good and bad thing I suppose.

  • Haskell is about as powerful and productive as languages such as Ruby or Python--you lose some dynamic flexibility, but you gain the bug-prevention and syntactic plasticity as above. On the other hand, compiled Haskell is dramatically faster than most dynamic languages, competitive with other garbage-collected, static-typed languages.

  • Haskell has a very straightforward foreign interface to C and lots of pure-Haskell libraries for common tasks, so it's more than acceptable for any actual job that you could imagine writing in some mix of C and a higher-level language with C bindings. On the other hand, interfacing to other languages can be a crapshoot, so if you really need a particular library that doesn't have a good C interface, things could get ugly.

  • Using Haskell effectively generally means abandoning OOP style, in case that bothers you. Haskell makes a fine faux-impure/imperative language, and of course is functional at heart, but good OOP style tends to clash badly and is best avoided. This isn't too bad, since functional idioms can subsume large sections of what OOP would be used for, but if you're used to OOP thinking it may be a painful adjustment.

[0]: In a few mostly-trivial cases, the type of a function so constrains the implementation that there is literally only one possible function with the desired signature, which therefore must be bug-free if it type-checks successfully (well, disregarding implementations that deliberately crash the program). People have even written "reverse type-checkers" that convert such function types into the functions they describe.

[1]: Namely: 1) "Scrap Your Boilerplate" and related approaches to datatype-agnostic programming, with limited forms of type introspection and whatnot; 2) Type-level metaprogramming, using a compiler flag to make the type-checker Turing-equivalent and writing "programs" that produce types as their output; 3) Template Haskell, which embeds regular Haskell code to run at compile time, generating code and applying transformations to the AST.

camccann
Speaking of the Haskell community being active... I'm glad people like my answer, but I was hoping someone would do something similar for Erlang. :(
camccann
I disagree that purity is over-hyped. Purity has a lot of wonderful consequences on the meaning of type signatures (often there's just one thing to do with the type, very often just one sensible thing), on parallelism, possible optimizations and more.
Peaker
There's a certain irony to gaining a gold badge for a closed question.
Beska
@Beska: As they say, "Not all that glitters..."! I'll just chalk it up as having done a good enough job giving a fair, polite, informative answer to a question with an awkward amount of flamebait potential (not that I think the questioner intended it as such).
camccann
@camccann: no offense intended...it's a good answer. It's just unusual.
Beska
Excellent answer. Could you elaborate on the `Type-level metaprogramming, using a compiler flag to make the type-checker Turing-equivalent and writing "programs" that produce types as their output` part? Thanks!
Wei Hu
@Wei Hu: That's a rather large topic, which this comment box is too small to contain--a good starting point would be [the material here](http://okmij.org/ftp/Haskell/types.html), which is where I learned most of what I know on the subject.
camccann
@camccann, I was looking for more specific "compiler flags", and a few concrete examples of "programs that produce types as output". I'm more familiar with the other two approaches.
Wei Hu
@Wei Hu: Relevant extensions are usually some of `UndecidableInstances`, `MultiParamTypeClasses`, `OverlappingInstances`, `FunctionalDependencies`, `TypeFamilies`, or a few others. The first of those is the "make type checking Turing-complete" flag. A simple, concrete example is lists of a fixed size, where `concat` consists of two functions: One term-level, to append one list's elements to the other, and one type-level, to sum the lengths to get the new size. The [HList library](http://hackage.haskell.org/package/HList) goes further, with e.g. indexing a list based on element type.
camccann
@Wei Hu: There's also plenty of proof-of-concept concrete examples on the page I linked to, and elsewhere on that site--but it all boils down to writing arbitrary functions between types (accomplished with functional dependencies and/or type families), combined with using types to choose between bits of code (which is what conventional type classes do). I can dig up more examples or go into more detail if you want, but preferably over email or otherwise something less constraining than this...
camccann
+16  A: 

You might find this article interesting. The writer implemented a bitTorrent client (a fairly large project) in first erlang and then haskell. Some of the comparison is sort of specific to bitTorrent but I feel that most of it holds in general.

voxcogitatio
That's a great link, highly recommended. It's also an unusually fair and informative comparison between languages, not the usual "this terrible code I wrote in language X proves my favorite language, Y, is better" fare.
camccann
+5  A: 

My contribution to the flame-war - Haskell is awesome because of:

  • Purity
  • Type system
  • Type-classes

Let me put it this way: Does Erlang have something like Hoogle? Didn't think so. Case closed.

Let me explain, by example:

Let's say I'm implementing quick-sort and I want to separate my list to two parts, those smaller than the pivot and those greater or equal. Will I loop on those numbers to separate them to two groups like I would in, say, Python? Been there, done that. It would be boring to loop or recurse on it... Haskell's library probably has a "higher order function" to do it all for me.

The function I'm looking for will take a list of "A"s [a], a "conditional on As" a -> Bool and returns two lists of "A"s to me ([a], [a]).

Hoogle [a] -> (a -> Bool) -> ([a], [a]):

Prelude break :: (a -> Bool) -> [a] -> ([a], [a])
Prelude span :: (a -> Bool) -> [a] -> ([a], [a])
Data.List partition :: (a -> Bool) -> [a] -> ([a], [a])

So it finds three functions that fit this type (order of arguments doesn't matter), all of which do useful things; but here partition is what we want.

Instead of a boring loop, our code is:

(under, over) = partition (< pivot) nums

Hoogle is very cool, but it is only possible due to the sheer awesomeness of Haskell. In C a function like void mysteriousFunc(void) can do absolutely anything. In Haskell the types tell us a lot about the code, and the fact that the compiler type-checks our program already assures us quite a lot and may catch bugs a-plenty.

yairchu
+3  A: 

Haskell is a well thought-out, powerful language. Not just the broad strokes but also the details are right -- good module system, great package manager, nice error messages. You may not like indentational syntaxes; but as far as they go, Haskell's is well-implemented and clear.

Erlang gives you a lot more in the way of parallel programming than it offers for functional programming. As a language, it's pretty rough -- no hierarchical modules, goofy Prolog-derived syntax, awkward error messages. If you'd like to learn about how to organize and manage large multi-process systems, Erlang is a great start -- but that's not functional programming qua functional programming.

Many fine things about FP are only realizable in a typed setting. Bounded side-effects, marked by types, allow powerful optimizations; and rich, expressive types make libraries easier to work with and errors easier to catch. It says a lot that Erlang has bolted on type-checking with Dialyzer. Haskell is a practical, pleasant environment in which to explore typed functional programming.

Jason Dusek
I think there's a general consensus that Haskell's module system has much to improve :-)But it's not that big a deal, because type-classes cover any missing functionality.
Peaker
There is much to improve relative to ML; but, relative to Erlang's, the Haskell module system is amazing.
Jason Dusek
+5  A: 

So, erlang is used in production at some startups you may have heard of, e.g., facebook, heroku, reddit, github. MochiMedia just sold for 70 million or something and their core technology platform is erlang. Count that as a vote for "gets stuff done".

mwt
+3  A: 

(This is just a note to leander's link to Peyton Jones' Haskell+Erlang talk, but I can't figure out how to make it one.)

It of course can't go very deep, but if you're wondering "Erlang or Haskell?" maybe you'd find some food for thought in the extended interview of Erlang designer Joe Anderson together with Peyton Jones; I think it was connected to Peyton Jones' Erlang Factory talk. You can extract a transcript from the page as well.

applicative
You need at least [50 reputation](http://stackoverflow.com/faq#reputation) to comment on other people's answers, for what it's worth. You'll be there soon enough!
camccann