Regardless of how someone feels about a particular language, I don’t understand why they would tell someone else to stop posting articles about it. If you don’t like go stories, filter out the go tag and you’ll never see them.
Except this one. It’s missing the go tag. :)
eh yeah, I debated adding Go and/or Haskell tags but in the end this isn’t really about either language. It’s more about some turbulent attitudes in the programming community. Being interested/disinterested in Haskell or Go should have very little to do with liking or disliking the content of this blog. Well that’s how my thinking went, I wonder if I was wrong…
Also, maybe a META tag.
Also, meta doesn’t work either. Lobste.rs already does an excellent job addressing this problem. What could we possibly do to make it better? The blog wasn’t supposed to be about Lobste.rs either.
Perhaps the “rant” tag? Not that this is overly rant-y, but it is in that direction.
This isn’t really a rant though. There’s a clear purpose, arguments are somewhat defined, and it doesn’t just rage all over people who disagree. I think there’s a real discussion to be had based on this. Where as most rants wouldn’t facilitate deeper discussion. I think most rants are probably off topic or low quality and would get downvoted, even if they had their own category.
I’ve been thinking about this same issue quite a bit lately. I also put myself in the camp of “not smart enough to Haskell”. :)
I know Haskell can prevent a class of errors at compile time but I’m curious if anyone knows if that comes at a higher cost of other types of errors. For example, I find Haskell (and functional languages in general) to be less readable than their imperative counterparts. Does poor readability cause errors when code reviewing or when translating requirements to code? Does abstracting the underlying hardware to high level abstractions cause performance issues down the road?
I’d be curious to hear from functional language folks and from people who used to be functional programmers and have switched back to imperative languages.
Ultimately I agree with kellogh that programming is not the end goal. It seems like it’s possible to write solid code (or shit code) in any language. There are trade offs to everything. I personally love Go because it’s simple and easy for me to reason about.
For example, I find Haskell (and functional languages in general) to be less readable than their imperative counterparts.
It’s interesting because my non-technical friends find imperative languages to be equally less readable as compared to functional languages. This may sound like hyperbole. But bear with me, because I truly believe there’s something important that’s revealed about our assumptions here.
So what exactly do I mean? You learned one way of formulating logic and now it feels natural to you. But I argue there’s nothing inherently natural about it. At least not in a way that isn’t inherently true of functional programming or logic programming or…
Learned patterns do feel natural, but you probably could have just as easily learned some other paradigm and then have argued that imperative languages were difficult to read.
Does poor readability cause errors when code reviewing or when translating requirements to code?
The salient point here is that this whole “functional programming just isn’t as readable” argument is specious: once you learn the idioms, it isn’t true. Also keep in mind, you had to do the same with the imperative paradigm as well.
So no, it doesn’t, because people who have learned functional paradigms don’t suffer from this mythical poor readability ailment. Granted, if you aren’t familiar with a given paradigm, then it’s legitimate to state that for you there is potentially an issue of readability.
My advice? Learn functional programming! :) It really isn’t as hard as it might seem.
I’ve done a fair amount of CL (the One True Lisp ;)), Clojure, and OCaml, dabbled with Erlang, and poked about with a couple other functional languages, and Haskell is still a language I view in the same light as XKCD. However, the fact that I don’t care for the language at all doesn’t mean I’m going to start telling people to stop using it. At the end of the day, build useful, interesting stuff in whatever language gets the job done. For me, that’s mostly Go with some C. For others, it might be Haskell. I don’t really care.
It’s self-deprecating humor though, as parts of xkcd is written in Haskell.
Learn functional programming! :) It really isn’t as hard as it might seem.
I wholeheartedly and unequivocally agree.
However, I’d like to maybe elaborate a bit on this “FP has poor readability” notion. I basically agree with your conclusion (that many of us got used to a different paradigm, so something foreign can be difficult to pick up). But I think there’s more to it then that, at least, for Haskell. (And I know you didn’t mention a specific language, but that’s what I’m going to talk about.)
When starting Haskell, I primarily struggled with two things. The first was being able to read someone else’s code (like, a piece of the standard library or a popular package). The second was laziness. The first is crucial for me personally, because that’s one of the primary ways that I pick up a new language.
I attribute the difficulty of reading someone else’s Haskell source code with the prevalence of Haskell extensions (GADTs, type families, fun deps, existential quantification, higher-rank polymorphism) and the absolute necessity to understand monads and monad transformers.
To your point, it may be the case that if monads were only called Warm Fuzzy Things, it wouldn’t have been so hard. But the bottom line is, I didn’t completely understand them, and it made reading source code (or even the Haddock documentation) incredibly difficult. Once I had that “ah ha!” moment about monads, it’s truly amazing how much code and documentation became almost immediately accessible to me. But it took a long time to get there.
Beyond that, Haskell is a dumping grounds for new academic research. (Which is a good thing!) But as curious programmers that like shiny new things (me included), it’s hard to resist an opportunity to use those things when the opportunity presents itself. But this imposes a huge hurdle on beginning programmers (or, just programmers new to FP in general) that learn by reading someone else’s code.
In general, I don’t think FP has poor readability. But I do think there are some concrete hurdles that beginners need to overcome to learn a language like Haskell. But as should be clear, these hurdles don’t really apply to functional programming in general, but rather, to Haskell specifically. (In my experience.) But we shouldn’t blame beginners for conflating Haskell with all of functional programming. :-)
You learned one way of formulating logic and now it feels natural to you. But I argue there’s nothing inherently natural about it.
Good point. Certain elements (e.g. tail recursion instead of a loop) feels very unnatural but I certainly have a bias.
I’m going to give it another go. I definitely know a lot of smart people who are functional programmers.
You really need to qualify readability before talking about it. The only sensible definition of readability that I’ve found is “to what extent does this code preserve equational reasoning” - a definition which is not only simple but also measurable.
Which is exactly why I find Haskell to be readable.
Does abstracting the underlying hardware to high level abstractions cause performance issues down the road?
Haskell is extremely fast precisely because it’s high-level. A compiler has deep introspection into your code. For example, it can inline code, automatically specialise, fuse equations and decide when things should be evaluated.
It seems like it’s possible to write solid code (or shit code) in any language.
I don’t think this is true. Would you be so diplomatic to Malbolge, INTERCAL or Whitespace?
I agree that programming is not the end goal. You use the tool that is best for the job. Go happens to be a very good tool for distributed systems.
Having said that, strict functional languages like Haskell sometimes are the best tool for the job. In my compilers class in university, we developed a compiler in OCaml. Things like algebraic datatypes and pattern matching come in really handy when you’re processing a complex AST. I wouldn’t say functional programming languages are less readable. If you get familiar with the language and do things in an idiomatic way, the code can be very clear and concise. Also, you tend not to run into bugs because the compiler detects a lot of them as type errors (although the compiler error messages can sometimes be really cryptic).
One more point to the readability of code. The longest part of the software development lifecycle (open source or otherwise) is maintenance. If the code you wrote truly has no side effects then it should be really obvious what’s going on when you go to track down a bug 5 months after you wrote the code. Of course this may or may not have anything to do with the language (though perl is fairly frequently a write once language) but there are languages that take longer, and are generally coded in a fashion that’s harder to troubleshoot and read later on. For instance, concurrency in java can be done and is more easy to read than in assembler. There are languages that just about any developer can jump in and read and figure out what’s going on… now being that I’m not smart enough to learn Haskell I have no idea what it looks like.
I don’t particularly like Go, for probably-subjective reasons, but I would still like to read technical articles about it. It seems obviously on-topic and relevant, so the request to stop posting about Go comes across as rude.
I believe Go is actively harming the software industry by providing a very incapable tool for building working software, yet it’s presented as a real alternative. I do not think it’s responsible to let others get introduced to such silliness.
I would have to disagree, as I find it quite suitable for building useful real world systems. I believe the CoreOS people would also disagree with you, as would many other people and organisations.
I will have to disagree and claim that the suitability is an illusion.
I, like many others, have built useful real-world systems in other languages. I didn’t start using Go because I was forced to. I’ll leave it at that.
Go like many languages is suitable for some tasks, and not for others. What about it is actually harming the industry, other than cases where developers misuse it (something that can happen with any tool)?
No parametric polymorphism (i.e. generics) - let’s not even go past this point. It’s so fundamental that giving it up is accepting defeat by your programming language.
Types are proofs (see the Curry-Howard isomorphism) - this has many consequences but one is that we can use types to prove properties about values and functions. Easy, right? People will say “I don’t care about proving that an int is an int” but they’re missing a huge implications - one being: parametric functions create cases where there’s only a limited amount of implementations.
Given a function with the type:
a -> a
(i.e. a implies a)
What are the possible implementation(s)? Let’s try to implement it:
parametric :: a -> a
parametric a = _
What can we put in the underscore hole? We need to produce an a, what are the possible a values which we have in scope? The only reasonable answer we have is a. This means, that given the signature a -> a, there is only a single implementation.
a -> a
We don’t need anything else from this function, no tests, no names, no comments - nothing but the type signature to know exactly what this function does.
That’s a pretty simple example, right? Let’s take a real world problem that I had yesterday:
I wanted a function which would take a list of disjunctive types and give me a list of just the right sides:
[Either3 a b c] -> [c]
Now, I could write this function directly against the list and Either3 types but there’s a chance I could do something like:
getRights :: [Either3 a b c] -> [c]
getRights xs = 
So, getting all the rights from my list returns an empty list - not what I want! If we make this type signature very generic, then we get to a place where we only have a single possible implementation:
unite :: (Monad m, Plus m, Foldable t) => m (t a) -> m a
unite value = value >>= foldMapPlus return
Here are example usages:
unite [Right 1, Right 2, Left "Whoops", Middle False, Right 3]
-- [1, 2, 3]
unite [Just 1, Nothing, Just 2]
-- [1, 2]
Not only have we specified exactly what should happen in the type but we’ve gotten a function which works for infinite types.
I consider writing programs without free theorems to be absolutely archaic. Recommending for people to do exactly that (by advocating Go, for example) is harmful.
You didn’t actually say how it was harming the industry. You just stated that you prefer programming languages with certain properties.
Also, it’s clear that you care very deeply about advocating for the functional paradigm. It would help your case if you didn’t include flame bait in your comments. (For instance, I’ve used Go effectively. But your comments would have me believe that I’m just deluded. But I’ve also used Haskell effectively. Am I deluded about that, too?)
It’s not a preference, advocating programming without free theorems is harmful. I did say that:
And yes, I believe it’s an illusion that Go is effective at solving problems.
You could argue the same about PHP, Java or $whatever_language_you_dislike.
Yes and I will, keeping in mind that Java is the most capable.
That’s exactly like saying “Let’s not talk about drugs because they’re bad.” Well, how do you tell others that drugs are bad without talking about them, discussing them, etc?
The same argument has been made about sex-ed and abstinence-only education. Guess what, when persons who’ve only been told “just don’t do it” do it and don’t know the first thing about the consequences, bad things happen.
So let the topic come up here. And if Go really is so terrible, then let it be discussed. Give others the opportunity to learn and understand what makes Go the “literally Hitler” of programming languages (or whatever might be good about it).
Let’s talk about drugs. Let’s not present drugs to people without experience, telling them that it’s a great idea.
Go does exactly what it sets out to do: make solving Google’s problems using code easier. Anything else is a nice side effect of Go making it easier for Google to do things.
Chris Allen (@bitemyapp) is a shining example of poe’s law. He sits around the #clojure IRC channel spewing this nonsense there too. Ignore him, please.
Having started to learn Haskell three times and hit the “I can’t read any existing code” wall three times, I think Haskell’s strength is also its weakness. It is so expressive at so many levels that it takes a lot of study just to understand the way the program has been expressed — before you can even begin to understand the program itself.
(Of course, when I manage to surmount the learning curve, it will all seem perfectly clear to me, so I’m writing this down while I have the chance.)
Other languages have “coding styles” or “idioms” that must be assimilated before comfortably reading someone else’s code, but they seem utterly trivial compared to the lofty meta-structures you have to understand to read the Haskell library. Understanding the Factory pattern vs. understanding Control.Arrow? Not even close.
For a more mainstream analogy, consider the wackier things that people have done with C++ templates, and how you have to approach reading that code. Now multiply that by 10. Or maybe square it. :)