ICFP report on the use of Haskell at Google
k1024.org
k1024.org
1. Immutable datastructures make it a lot easier to reason about data flow and to write correct code.
2. Static typing helps write cleaner, more explicit APIs.
3. Programming effectively in a functional style is more difficult than banging out imperative code.
I wonder why they didn't try Scala. With Google's extensive Java infrastructure that seems like a more logical choice. Certainly the problems they discuss with Haskell's string handling and debugging support wouldn't be issues in Scala.
But aside from that, the cluster balancer runs in just 5MB of RAM (RSS). I'm not familiar with Scala, but I doubt any JVM can run in just that; and the way we deploy this software, we like it to use as few memory as possible.
Thanks for taking the time to write this up. Detailed descriptions of real-world applications of FP languages are always welcome.
As someone who is just starting to learn functional programming, do you believe this is because "we've" all been taught to think imperatively, and functional is just new to us? Or is it something inherent in functional style coding?
Doubtless others will disagree though. Maybe we don't all have the same mental strengths and weaknesses.
At least in some cases, I think that's the expected result: consider the difficulty of reversing a singly linked list in-place and reversing it applicatively.
There is stuff to learn in every language :)
Recursive cases in languages with tail-call optimization are like inductive reasoning in mathematics - "How long is a list? If it's empty, zero, otherwise one (for the head) plus however long the rest is."
(Node: I don't no haskell)
(Sometimes I get in trouble when I try to distinguish between "new functional" and "old functional", but despite superficial similarities they are diametrically philosophically opposed. Old functional, embodied by Lisp, works by trying to empower the programmer, and builds on that; new functional works by restricting the programmer and building on what guarantees we get from those restrictions. Haskell and Lisp may share some terminology when it comes to list manipulation but I would actually put them very, very far apart in my grand map of programming languages; they take one step together, the first lambda calculus step, and then immediately begin sprinting in opposite directions.)
I'm also not sure I'd go as far as to say "restricts" as much as demarcates. Composing existing code has been vary difficult in imperative languages (practically impossible when you have to deal with things like memory management and/or threading).
If you have a system where 95% of it is functional, cool, you've eliminated 95% of the places where you have to double-check for dataflow/mutability-related bugs. (To heavily paraphrase jerf's comment: functional programming is about accepting restrictions that make debugging simpler.) Make the system as clean as feasible, but don't get bent out of shape trying to get the last 5% FP-approved. It's probably less trouble to just know that's the hairy part.
The big idea in functional programming is that working with immutable data structures makes a lot of annoying bugs go away, and goddamnit, they're right. Does that mean you need to go 100% immutable? No - it's just a good default.
FP-style programming without (generational) garbage collection is really awkward, though - immutability means you're going to be creating a lot of temporary data structures. Good language implementations will recognize this and just stack-allocate them or let them go in the first collection.
Haskell is unusually strict in that regard, turning what is normally a design option into an all-or-nothing situation.
Edit: I know there are a few ways around it via monads, but the culture surrounding Haskell seems quite a bit more likely to treat state/purity as an all-or-nothing issue than the others'. Maybe I'm making inaccurate assumptions about Haskell based on the loudest members of its community, though.
(There is also the good-old-IORef, but I avoid IO for anything that's not input or output.)
With Haskell, you know that something that claims to be pure is.
I've since moved on to a software engineering role, but there's something to be said about the freedom (e.g., picking your tools) that exists when you're writing software that only you are responsible for.
And the stack trace example is not related to ghci. You run software in production, and it crashes. What do you get?