When you start to learn Haskell, many people will tell you it’s hard. When you say, “Oh, it is a bit hard because I have no background at all in programming,” many people imply that that might actually make it easier. I think the idea is that, since functional programming languages are so different from other languages, it might be easier to start somewhat tabula rasa and not have to retrain your brain to think about programming in an entirely different way. To me, it’s a bit like saying that if you already know English, then learning a second language will be more difficult for you than if you didn’t know any language.

I can see why one might think this, but I think it understates the difficulties that a nonprogrammer learning Haskell as a first programming language faces. When I started about 5 months ago, I was a sort of guinea pig for my teacher, an experiment to see how different it would be to teach a nonprogrammer (I don’t have any kind of math background to speak of either and have not had a math class in >20 years). Indeed, when I told him I was going to write this blog post, he confessed he hadn’t, in the beginning, really expected me to understand anything at all. I am glad he didn’t tell me that before (he has always appeared much more confident in my ability to learn Haskell than I have been, because he believes nearly anyone can). I am reasonably confident about my intellectual capacities, but I also know my weaknesses, and during the first couple of months, I thought there was no way in hell I would ever learn Haskell to any kind of competence. I hit a learning curve approximately like this:

Only I didn’t have those abs.

The first and most obvious problem with deciding to learn programming with no experience actually has nothing to do with Haskell. True Confession: I didn’t know Github existed until I started learning Haskell; I didn’t even know what version control was. So, as I was starting with Haskell, I had Linux, Git, an invitation to join an IRC channel (a wut?) and, er, “a text editor” thrown at me. Seems silly, yes? Well, when your primary use of computers has previously been Googling recipes and letting your kids play Minecraft, and all of a sudden someone tells you to open up your “REPL” (whatever that is–yeah, yeah, I know now) and your text editor, you…try really hard to pretend you know how to do those things while Googling furiously. I still have more things to learn about Linux and git–a lot more–along with learning Emacs, but they are mere constituents in a continually growing pile of stuff I still need to learn. Anyone who wants to learn programming has to learn all these things at some point, but programmers starting to learn Haskell wouldn’t.

If you successfully figure out how to get your terminal, text editor, and REPL going and push something to a Github repo (and then hear, “Well, you should write the text files in markdown,” and start rending garments), you hit the second wall: all the Haskell materials I’ve seen assume some background in programming and, often, mathematics as well. Learn You a Haskell for Great Good is usually recommended to inexperienced programmers wanting to learn Haskell because it is written in a friendly and approachable way. However, it says clearly in the introduction that even it assumes you have some experience with imperative programming languages, and that assumption shows. I’m taking the FP101x class through edX right now, and it also assumes you have at least a year of programming experience. Well, what’s wrong with that? There are two problems, from the perspective of a nonprogrammer. The first is the vocabulary. What is a compiler? What is “statically (as opposed to dynamically) typed?” What are “imperative” or “object-oriented” languages* and how are they different from what I’m trying to learn? What is “syntactic sugar?” Why is printing something considered a “side effect?” What are these ‘foo’ and ‘bar’ functions? Most of these concepts are familiar, though, to anyone with programming experience.

The second problem is that many of these materials try to teach functional programming concepts by analogy to imperative language features. Even leaving aside the question for now of whether that is an effective way to teach those concepts**, if you don’t know the imperative language concept used for the analogy, then the whole thing is more confusing than helpful. I don’t understand how other languages loop over lists, not really, and so explaining list functions in Haskell in terms of looping is confusing and unhelpful, especially because as a former syntactician, I was already familiar with recursion.

A final, related problem is what I call the Lack of Purpose problem; learning about types is great, but I didn’t know what to do with it all. I had no way to apply most of what I was learning. Programmers, even inexperienced ones, have ideas of what kinds of things you are likely to want to accomplish with computer programs, and often have some understanding of the kinds of steps you could reasonably break those goals into. Nonprogrammers are less likely to have that foundation. Yes, I use computers to accomplish a variety of tasks, but I usually have little idea of what else might be possible or what kinds of functions might make that happen. Look, don’t make fun of me. I know. But it’s just something that never crosses my mind in my daily life because I’m not a programmer.

Try to imagine, for comparison, that you are not a welder. You don’t really think too much about where one would use welding or what kinds of problems it might be used to solve. If someone suddenly launched into a spiel about the physical properties of acetylene welding, so you could understand the theory of it, you might think to yourself, well, this is all very interesting, but what would I ever use this information for? It is more difficult to retain and assimilate information you have no immediate use for.

For me, this problem has been gradually ameliorated because my teacher patiently walks me through reading code. After he wrote this handy URL shortener, he spent a couple of hours explaining the code to me, line by line. We’ve done similar, albeit shorter, exercises of this sort on other occasions. Finally, I am starting to get a sense of what purpose I might put Haskell to and what kinds of steps I would need to follow to do that; finally, functions and types have a context. So, the learning curve is starting to decrease in severity now, but the initial difficulties meant I almost didn’t make it. I wouldn’t have without a teacher who invested large amounts of time and reassured me I could do it if I just stuck with it and did the work.

Most of the difficulties I had in the beginning are not the things that experienced programmers would find difficult. That doesn’t mean they don’t have their own issues to overcome, like learning to think about programming in a new way, but it is a different experience.

* Honestly, I still don’t really understand why people like imperative and OO languages. Mutation might be unavoidable at times, but hey if you read what I’m linking to here, it seems better to avoid where possible. (EDIT to appease Hacker News nitpickers. Is this the only part of this essay y’all read or just the only part you respond to? Because, seriously, those responses are weak. Up your game, Hacker News.) Why do you want so many, seemingly poorly controlled side effects? Why don’t you want strong typing? Well, to each his own, I guess, but these things seem prima facie to decrease the safety of and ease of reasoning about programming.

**In my experience teaching human languages, I suspect the analogy hurts more than it helps. The goal for fluency in a human language is to get you thinking in the target language, not translating in your head, a process that a) slows you down considerably and b) leads to a lot of mistakes. English speakers learning Irish Gaelic, e.g., make word-order mistakes all the time. Trying to speak Japanese by analogy with English means learners frequently think suki (‘like’) and hoshii (‘want’) should be verbs, leading to syntax errors. I suspect it’s the same with computer languages: learn to think in the target language in the beginning (or as soon as possible) for much long-term benefit. Of the two footnotes, this is the one I wish people would engage with.