5 ms·
As usual in these threads about Go, I really wish people would consider Haskell as a nice alternative. A lot of people write Haskell off as "academic" or "impra
by tikhonj 14y ago
As usual in these threads about Go, I really wish people would consider Haskell as a nice alternative. A lot of people write Haskell off as "academic" or "impractical", which I feel is not an entirely fair assessment.
Particularly: Haskell is fast, concurrent by design (whatever that means, I'm sure Haskell is :P), typed but not cumbersome or ugly (less cumbersome and ugly than Go's types, even) and--most importantly for this article--does error handling really well.
In a certain sense, Haskell's main method for handling errors is actually similar to Go's. It returns a type corresponding to either an error or a value (this type, naturally, is called Either). This method is special, oddly enough, because it isn't special: Either is just a normal Haskell type so the error checking isn't baked into the language.
Coming from another language, you would expect to have to check your return value each time. That is, you fear your code would look like this pseudocode:
if isError val1
then pass val1
else val2 <- someFunction val1
if isError val2
...
However, this is not the case! The people implementing Either noticed that this was a very common case: most of the time, you want to propagate an error value outwards and only do any work on a valid value. So you can actually just write code like this:
do val1 <- someValue
val2 <- someFunction val1
val3 <- someFunction val2
someFunction val3
then, if any of the values return an error, it gets propagated to the end of the code. Then, when you want to check if you actually got a valid value--maybe in some central location in your code, or wherever is convenient--you can just use a normal case analysis.
Additionally, while the errors do pass through essentially silently, the type checker does ensure you deal with them at some point before using or returning them. If you ever want to get the Int from a Either Error Int, you have to either handle the error case somehow or explicitly ignore it (e.g. with a partial pattern match). The latter option will generate a compiler warning, so you can't do it by accident without being notified.
So the mechanism is simple, but it can also stay out of your way syntactically. So what else is this good for? Well, it's just a normal data type, nothing special; you can use existing library functions with these values. For example, you can use the alternation operator <|> to find the first non-error value:
val1 <|> val2 <|> someFunction 5 <|> ...
This is often a very useful idiom which would be harder to write with a different way of handling errors. There are more utility functions like this (e.g. optional) that let you make your intents very clear at a high level. The optional function, for example, lets you do exactly what it claims: you can mark a value as "optional", meaning that any error from it will be ignored rather than propagated.
You can also layer on this error-handling logic on other similar effects. For example, there are some types (like LogicT) that represent backtracking search. Combining error-handling with nondeterminism gives you a question: should an error cause the whole computation to fail, or only that particular branch? The beauty is that you can choose either option: if you wrap LogicT with ErrorT (this is just like Either except it can be combined with other types) an error will cause the whole computation to fail; if you wrap ErrorT with LogicT, the error will only cause the current branch to fail. This not only makes it easy to choose one or the other, but also makes it very clear which one you did choose: it's right there in the type system in a very declarative fashion.
Haskell also has a bunch of other advantages which aren't worth going into here. I think anybody looking for something like Go--a fast, high-level, concise, typed alternative to Python--should definitely consider Haskell. While it may not seem so at first, I believe that Go and Haskell are good for a very similar set of problems and so actually overlap quite a bit.
If you really dislike some particular things about Haskell, you should also consider some similar languages like OCaml and F#. I personally prefer Haskell, but there are definitely good cases to be made for either of the other two.
- cletus 14y agoThis kind of comment kinda misses the point. Haskell (IMHO) won't ever be mainstream for much the same reasons Lisp never was (or will be?): it has an incredibly high learning curve (eg [1]). This is really the problem of the "pure" functional languages. Functional programming is suited to some tasks. With others the fit is almost tortuous. Imperative programming is well-suited to how we think and how we break down tasks. If you look at the popular languages they're pretty much all multi-paradigm (eg Ruby, Python, Go, C#, arguably even C++/Java) meaning they give you the low-hanging fruit of functional programming while still being in a relative sweet spot of being easy to learn yet reasonably expressive. Why I think Go has a very bright future ahead of it is that it is the first of these multi-paradigm language to combine all these features: - easy to learn (seriously, go look at how short [2] is; you can knock that out in an afternoon); - it is minimal. I LOVE Go's minimal OO model for example; and - it is statically typed. If you look at the other statically typed multi-paradigm languages you have C#, which is generally well-regarded... except (Mono notwithstanding) it is very Windows-centric. Java is, well, Java. C++ is incredibly complicated. The only thing Go is missing is a mode for (semi-)manual memory management. I'm thinking something like Obj-C's ARC (in iOS 5+) and it could well supplant C/C++ for the vast majority of their (already shriking) use cases... eventually (Go has some work to do on speed). [1]: http://stackoverflow.com/questions/377082/how-long-does-it-take-for-you-to-be-comfortable-with-haskell http://stackoverflow.com/questions/377082/how-long-does-it-t... [2]: http://www.miek.nl/projects/learninggo/ http://www.miek.nl/projects/learninggo/
- cageface 14y agoHaskell (IMHO) won't ever be mainstream for much the same reasons Lisp never was (or will be?): it has an incredibly high learning curve (eg [1]). Bingo. Anybody that thinks Haskell will ever escape its niche has not spent enough time working with rank & file programmers. That doesn't mean you shouldn't consider it or that it can't find a large enough niche to sustain itself but it does mean that it's unlikely to ever overcome what Carmack refers to as "externalities" for a lot of prospective users.
- theaeolist 14y agoThis kind of comment kind of misses the point. The monadic style of threading error values is perfectly compatible with imperative programming if only language designers knew about it.