8 ms·
I have to admit that I'm really on the fence about Haskell. My major gripe with this point I think is point (3). Haskell has (IMHO) gone down a similar road to
by cletus 14y ago
I have to admit that I'm really on the fence about Haskell. My major gripe with this point I think is point (3).
Haskell has (IMHO) gone down a similar road to Scala. Scala has literally tied itself into knots to make statically typesafe collections (amongst other things). I see parallels with Haskell (maintaining functionality purity but dealing with the "outside world" through monads).
I'm not saying this is wrong. What I am saying is that the gap between making something 99% consistent and 100% consistent is often huge in terms of complexity. This is why I think the so-called mixed paradigm languages (Python, Ruby, even C#) have done so well since you can use these programming models while still writing easy-to-understand imperative code.
This is also why I'm so bullish on the future of Go. Someone wrote a book called Learning Go that tells you most of what you need to know and you can knock that out in an afternoon. Go has a good model for parallel programming and a simple syntax. It has made the choice of simplicity over completeness (eg no "generics").
The net effect is that Haskell will never be mainstream (IMHO) because it's too complex whereas Go probably will be because it's incredibly simple.
We've had complex functional languages (eg Lisp) for decades. Yet they haven't gone mainstream. You have to ask yourself why. Some pride themselves in using something so esoteric. Others attribute the lack of popularity to poor marketing or bad timing. The answer is (again, IMHO) is that simplicity matters.
Now it should be noted that we're talking about perceived simplicity. You can write multithreaded code in Java, C or C++ but getting it right is incredibly hard yet it can appear simple. The goal of any language I think should be to narrow or eliminate the gap between perceived simplicity and actual simplicity. IMHO Go does a remarkably good job of this.
FWIW Python and Go also play nice with C.
It's true functional programming does change the way you think but I think writing idiomatic Python or Ruby will get you much the same benefit at much lower cost.
- tikhonj 14y agoHaskell is also very simple--not from an implementation standpoint but from a semantics standpoint. Having polymorphism with no sub-typing (and no casting) is conceptually simple and easy to work with. Parametric polymorphism (like Java's generics but simpler and less horrible) is actually an extremely simple concept. The difficulty comes from a) implementing it in a stupid way after the fact (cough Java) or b) having sub-typing. Neither is necessary! In this day and age, semantics are far more important than implementation. You can fit Haskell's evaluation rules and its typing rules on one page. Haskell's syntax is also very simple and consistent. It has fewer constructs than most imperative languages--fewer constructs than anything short of Lisp. It just also happens to be much more flexible than other languages. Moreover, much of Haskell's syntax is very transparent syntax sugar. You can easily desguar it in your head. It makes code nicer to read but does not add any real complexity because it trivially maps to a bunch of simple function calls. Most of Haskell is a very transparent layer over a typed lambda calculus. Lambda calculus is basically one of the simplest possible constructs. Ignoring the type system for a moment, it has literally three concepts: functions, variables and application. We then throw in some very straight-forward extensions like numbers, add a bit of syntax sugar and a type system. The type system is also surprisingly simple. It has to be, for the inference to work! It's also very consistent in the way that is almost unique to mathematics. Consistency is pretty important. This is where I shall bring up the "Simple Made Easy"[1] talk. It comes up a lot in these discussions, for a reason: most people mix the two up. I don't agree with all the points in the talk, but the core message is completely correct and very valuable. [1]: http://www.infoq.com/presentations/Simple-Made-Easy http://www.infoq.com/presentations/Simple-Made-Easy Simplicity is valuable. And Haskell, for all its being hard to learn, is simple. IO is a great example here. Monads are difficult to learn, granted. But they are not complex. Rather, they are abstract. In fact, monads are extremely simple; the actual difficulty is twofold: it's not immediately obvious why they matter and they're too abstract to permit any analogies. Ultimately, a monad in Haskell is just any type with three simple functions that behave consistently--it's just an interface. Go is not particularly simple; rather, it's easy. It's familiar. The syntax is more arbitrary, but it is C-like. The built-in constructs like loops are more complex and arbitrary (Haskell, after all, has no built-in iteration at all), but hey, it's C-like. The exposed features? Again, fairly arbitrary. That's how I would sum up Go's design: arbitrary. And mostly C-like. Where C itself is pretty arbitrary. Especially from a semantics standpoint. Essentially, Go has whatever the designers felt like adding. Just look at all the different ways you can write a for-loop! Or the fact that you have a loop at all. Haskell, on the other hand, has a deep and elegant underlying theory which ensures that different parts of the language are all consistent. Haskell is much less arbitrary. Most of the features naturally go together. Many are just generalizations or facets of the same concept. Even the complicated, advanced features like "type families" or "GASDTs" are just fairly natural extensions of Haskell's basic concepts. It's very much akin to mathematical ideas, which have an elegance and consistency eluding most other languages. Here's a particular example of how the features fit together: algebraic data types. Haskell essentially has two fundamental ways to create data types: you can combine fields into a record (like a struct) or you can have a choice (a tagged or disjoint union). The really neat bit? These aren't arbitrary--they're actually deeply related. In fact, they're duals of each other. Having both makes the most sense. It also gives you a much better way to signal errors. In Go, for whatever reason, errors are essentially built into the language as an implicit tuple. However, in practice, you either have a result or an error. If you have an error, the result is meaningless; if you have a result, you shouldn't have any error! So it makes much more sense to represent errors as a variant, a choice--a sum type. This lets Haskell avoid baking in error handling into the language, making it simpler. Haskell is as mixed-paradigm as the languages you listed. Those languages are imperative with some weak support for functional programming. Haskell is functional with some weak support for imperative programming. It's the same idea, inverted. Except Haskell can also support things like non-deterministic and logic programming. It's just that, for some reason, when people say "mixed-paradigm" what they really mean is "imperative with some functional support" and never "functional with some imperative support". Sure, Haskell's syntax for mutable structures is awkward. But have you seen C#'s or Python's or even Go's syntax for functional programming? Compared to Haskell, it's just as awkward! And Haskell's "syntax" for mutable constructs is just a library; it can be improved. It just turns out that imperative features aren't useful enough for experienced Haskellers to warrant the improved syntax. (Also GHC sucks at optimizing sufficiently complex imperative code, I gather.) There's a nice example of what you can do on Lennart Augustss's blog[2]. He essentially embedded a very C-like language into Haskell without using macros. So it's certainly possible, just not worth it. [2]: http://augustss.blogspot.com/2007/08/programming-in-c-ummm-haskell-heres.html http://augustss.blogspot.com/2007/08/programming-in-c-ummm-h... So yes, perhaps Haskell will never be popular. But that's a social issue. It is not an issue of the language's qualities. And it shouldn't stop you from using Haskell. At your startupt. Hint, hint.
- pekk 14y agoIt is an issue of the language's qualities if it does not really make it easier to reason about code. I find reason to question the simplicity of something which is widely acknowledged to take a lot of time to learn, to be mind-bending, and which seems to be impossible to explain simply - without deep theoretical background, academic citations or oversimplifications acknowledged as misleading. I think it would be mature for the Haskell community to occasionally acknowledge a trade-off of the language. Haskell's flaws are not all "social issues." The virtues of survivors like C and LISP are not all "social issues".
- papsosouid 14y ago>It is an issue of the language's qualities if it does not really make it easier to reason about code. The primary point of haskell is making it easier to reason about your code. >I find reason to question the simplicity of something which is widely acknowledged to take a lot of time to learn, to be mind-bending, and which seems to be impossible to explain simply It takes a long time to learn any programming language. You create an invalid comparison when you compare learning language X++ after already learning X to learning language Y++ without having learned language Y. Haskell only takes longer to learn if you compare it to learning a language that is virtually identical semantically to a language you already know. And I don't know why you think it is impossible to explain haskell simply, there's a reason everyone points to learnyouahaskell.com when people ask how to learn haskell. >The virtues of survivors like C and LISP are not all "social issues". How is lisp a "survivor" exactly? Haskell is more widely used than any lisp is.
- rafcavallaro 14y agoThe tiobe index has lisp in the top 20 (at 13th) while Haskell is at 33rd, so lisp is more popular than Haskell even though lisp is over a half century old. Being in the top twenty after 50 years looks like the very definition of "survivor" to me.
- papsosouid 14y ago
- papsosouid 14y ago>I see parallels with Haskell You are seeing things. >I'm not saying this is wrong. What I am saying is that the gap between making something 99% consistent and 100% consistent is often huge in terms of complexity. Haskell is a very simple, very consistent language. That is one of its biggest strengths. >The answer is (again, IMHO) is that simplicity matters. Except that lisp is not complex. Especially consider scheme, which is very simple and consistent. >It's true functional programming does change the way you think but I think writing idiomatic Python or Ruby will get you much the same benefit at much lower cost. Having gone from "I see the benefits of functional programming, but think a multi-paradigm language is the right way to do it" to outright revulsion when stuck using multi-paradigm languages, I think you might change your mind if you actually tried it. Ocaml and scala certainly sold me on haskell.
- gtani 14y agoYou can write simple scala, if you use case classes, type inference, wildcards, optional parens/periods, return "this" to make little pointfree method chains etc. You also need to avoid parameterized types and many corners of the type system that go with them. Look in Subramaniam's Pragmatic Press book on scala, you'll see lots of simple code that any ruby/PHP dev can grok, for analytics, sysadmin etc. Now it's true that a lot of people don't choose to write simple scala. Scala has a lot of features that other language designers know they need. Look how proud Hjelsberg was of co- and contravariance in C# 4.0 (I don't have a video waypoint, it's about 2/3 of way thru http://channel9.msdn.com/Blogs/matthijs/C-40-and-beyond-by-Anders-Hejlsberg http://channel9.msdn.com/Blogs/matthijs/C-40-and-beyond-by-A... (Also look at Learn You Haskell, for pretty straightforward haskell code (straightforward because he didn't have page-space to go into a lot of GHC extensions and advanced stuff)
- jes5199 14y agohmmm - your measure of "complexity" is not the consensus one. Scala has a lot of machinery in its type system, and Haskell has very little. LISP has even less. Scala may have been inspired by Haskell in some ways, but the experience of writing it is very different.
- alberich 14y agoWhat Lisp are you talking about? If Lisp isn't simple, what is, then? Sure, if you want to become a skilled programmer in Lisp, it would take many years. But that is applicable to anything in life after all. The original Lisp 1.5 Programmers Manual had 106 pages, including appendices and a glossary. Scheme specification is very small too. It may be arguable that the lots of parenthesis is unappeling, but not that the language is complex.
- platz 14y agoAlso, this sentiment is popularized as worse-is-better: http://www.jwz.org/doc/worse-is-better.html http://www.jwz.org/doc/worse-is-better.html
- zem 14y agoyou might prefer ocaml (i do) - it has a lot of the functional power of haskell, but is comfortably multi-paradigm, and in particular pushes neither purity nor laziness upon you. also, the ocaml community has been considerably revitalised in the last year or so, so now is a good time to get into it
- platz 14y agoI understand F# is in the ocaml family. Any reason why one would prefer ocaml over fsharp?
- jon_smark 14y agoThere are several reasons why one would prefer OCaml over F#: - OCaml is not tied to .NET. Obviously the converse also applies: if you need .NET integration then F# might be a better choice. - F# does not support some of the more advanced features of the OCaml type system, like polymorphic variants (open unions) and functors. These are very useful OCaml features, IMHO. - OCaml has gained some very interesting features since F# branched off, which again are not present in F#: modules as first class values, GADTs, and better control over module signatures. Overall, my recommendation is that unless you are really tied to .NET ecosystem, then OCaml is a more interesting language to learn.
- jules 14y agoOn the other hand, if you can use .NET, F# is a more practical language to learn. The F# standard libraries and .NET libraries and IDE are miles ahead of anything OCaml has, which in practice far outweighs anything else. If you're picking a language to learn new language concepts, I'd definitely pick OCaml over F# for its modules alone.
- profquail 14y agoA few counterpoints in favor of F#: - Even if your project doesn't need .NET integration, it's nice to have all of the .NET libraries (built-in or otherwise) at your disposal. OCaml also has some nice libraries, but nowhere near what .NET (or Java, for Scala) has -- so it's likely you'll have to implement your own library for some task if it's outside of the mainstream. - F# has also gained some interesting features since it's branched away from OCaml -- computation expressions (syntactic sugar for monads) and type providers (automatically-generated, strongly-typed interfaces to databases, JSON APIs, etc.), for example. - .NET has a mature and very fast garbage collector tuned for real world usage (e.g., people running C#/ASP.NET on large webservers). This hugely benefits F#'s performance. - You can use Visual Studio or MonoDevelop to write and debug F# apps, which makes it much nicer to use in practice. (Oh, and you can get Visual Studio Express for Web if you want to use VS and F# for free.) I don't have anything against OCaml, I just wanted to point out that F# certainly deserves consideration if you want to learn a new language (i.e., it's not a knock-off version of OCaml).
- banachtarski 14y agoComparing Lisp to C isn't fair. Both are arguably difficult to master, but one took off because chip manufacturers decided to optimize for it.
- martinced 14y agoOh, a bracket-style programmer (Java / C#) spitting his poison about Scala, Haskell and Lisp dialects all in one comment and somehow this gets voted up. I'm calling appeal to autorithy now. No, not people with lots of rep on SO for answering Java and C# question. I'm calling appeal to pg authority. This is ycombinator.com FFS! Go read "Beating the average", "What made Lisp different", etc. There are many very insightful things in these essays. After you'll have read them, you won't be upvoting these "I hate everything non-bracket styles / your language is a toy because it's not the most succesful one" comments. Actually after reading them you'll be downvoting these poisonous words...
- pcwalton 14y agoI don't think simplicity is as much of a recipe for language popularity as you claim. Scheme is a very simple language, far simpler than any of the languages you mentioned, yet it doesn't get much use in industry. Standard ML is a simple language, simple enough to be formally specified even. Most computer science students easily pick it up and learn it as part of a compilers course, so it's not that the language is simple in theory but hard to grasp. Lua is a wonderfully simple language, and it's found a good niche in games and configuration, yet it's nowhere near the popularity of its older, more complex sibling JavaScript. On the other hand, C++ is probably the most complex language on the planet and it's hugely popular. PHP is an incredibly complex language—it surprises almost everyone who uses it—and it's extremely popular as well. Language simplicity is just one of many factors influencing a language's success.
- camus 14y agoPHP C and C++ are popular because they are imperative languages. For non mathematicians , "imperativism" is far more easier to grasp than functional , closures , first order, monads , ... it is easy to understand what a IF statement does , what a FOR loop is , and a basic PROCEDURE or FUNCTION is. It is not easy at all to think in terms of pure functions , immutability , etc ... because you need to actually design you code before writting it. I dont think Haskell is hard because of the syntax , it is hard because it is a functional language.
- pcwalton 14y agoNone of the languages I listed feature purity, immutability, or monads. (Granted, Scheme and Standard ML do express a clear preference for immutability, but you can mutate all you want.) And closures are hardly an uncommon feature at this point, I'd say. Even C++ and PHP have them.
- tikhonj 14y agoYou say that, but it doesn't match my experience at all. I've taught high-schoolers basic Java and they had all sorts of problems with for-loops and procedures. In fact, it took me a while just to describe what a (mutable) variable was! To many of them, the idea of changing value was not intuitive at all. It didn't help that Java coopted well-known syntax from high-school algebra like x = 10 to mean something completely different. At my university, everyone started with a Scheme course followed by a Java course. The Scheme course starts out functionally, but never mentions it. People didn't have too many problems there except with recursion, and most of them got that after a couple of lessons. The Java course? Not so easy! People did have problems with if statements (why is it a statement and not an expression?). They also had problems with figuring out what was a reference in Java and what was passed by value. A lot of problems with that particular facet, in fact. In fact, the people without any programming experience before college had more problems with Java than with Scheme, despite the fact that the Java course was second. Basically, you're projecting your years of experience with imperative programming onto what you imagine a beginner thinks like. I do not think this is particularly accurate--it certainly doesn't match what I've seen in practice. For people with literally no programming experience, functional programming is not less natural at all. If anything, it makes more sense, because it fits with the minimal mathematical background everyone has.