How can I learn to think like a functional programmer?

Quora Feeds

Active Member
Andrea Ferro

This is going to be quite a long post.
Pass if you are in a hurry. Take popcorns and relax otherwise.

The obvious answer


Mostly you learn the same way you would learn any other thing about programming: by doing it over and over and by studying what others have done.
One catch is that if you have already learned to program non functionally, it will take you at least twice or trice as long to really learn how to program functionally (this may or may not be also true if you walk the other way).


A note on terminology

(you can skip this if you want)

Let me start by noting a problem of terminology. We often use "functional" as opposed to "imperative". And we also notice that the meaning of "functional" has somewhat changed in modern times. Languages that used to be considered prototypical functional languages are not what we today mean when we speak about functional languages.

I think we should use different terms, other than functional and imperative, as antithetical. I'd like to propose: declarative as antithetical to impertive, and procedural as antithetical to functional.
Most languages will then have different level of support of those concepts.
Haskell is declarative functional. Most other languages are imperative procedural. Languages like Lisp/Scheme are, at the core, also imperative procedural, but they very strongly encourage functional programming instead of procedural, therefore could very well be seen as being imperative functional (which are not in antithesis).


It's not just about declarative functional programming

(you can skip this if you want)

Like most things in computer programming, if you are used to think in a different way, you will initially have a tendency to slavishly translate your thoughts in the new language, instead of thinking in a new way (this also happens when you learn a human language: you initially think in your native language and translate, which is often both hard and bound to result in very poor expressiveness).

Examples of this abound. C programmers using C++ as a mere "better C". JavaScript programmers totally missing both his functional nature and his object oriented one. Clojure/Scala programmers that basically just program in Java, with a slightly modified syntax.
You can do pretty much the same thing with functional and declarative languages. You can program procedurally in Lisp/Scheme. You can even code imperatively in Haskell, if you try hard enough.
And this takes us to what, I believe, is why you asked this question: you have realised that there is more. Either you "feel" it or you noticed by comparing your code with that of experienced programmers.

How does a C programmer learn to program in C++ (not just using it as a "better C")? How does a Clojure programmer learn to program in Clojure instead of Java?
As said above: mostly by doing it over and over and studying the code written by others.


A little trick/exercise


One thing that helps a lot is to find a bunch (say half a dozen or more) non trivial problems that are implementable without using (or with very limited use) of frameworks and libraries. Those tend to require that you to tackle many different aspects of programming without tying you to pre-designed schemata.
Solve those problems and then take a 3~6 months break from them (and keep using the language for other tasks).
After the break, go back to them. You will likely be ashamed of your code.
Re-write your solutions from scratch. Then take another break (maybe a longer one).
Rinse and repeat. Even a dozen times, if needed.

The above exercise will force you to both see your own progress and re-evaluate your thoughts under the light of new knowledge/understanding.
This will help you clarify and solidify your understanding, including the ones that are latent or just present as an intuition.


It's all about abstractions


If you work with languages like Haskell, you will find that a lot of things can actually be expressed in terms of functions (something that you are unlikely to do in other languages). You'll also find that, as a beginner, you have a tendency to see "concrete" solutions, but when time passes you start to see "patterns" and "abstractions". You then notice how those abstractions can be composed in infinite different ways.

This will help a lot because the larger the number of cases where you have successfully used an abstraction, the better you understand the real nature of that abstraction, and the more likely you are to recognise a situation where it can be applied.

And this is, in fact, what you are after: thinking like a functional programmer means intuitively knowing that a given problem can be expressed in terms of a given abstraction (or rather compositions of abstractions).


Abstractions may seem hard


One problem with abstractions is that they are not immediately manifest. By definition they emerge as "commonalities" between different, and often apparently unrelated, situations.

The first time you find an abstract concept you cannot recognise it as such. The second time you may, but it's very uncommon to do it. Three times is, cognitively, the minimum number of occurrences before we recognise a pattern. However, with abstractions, this may not be enough because the nature of abstractions is that they appear in completely different and unrelated contexts, often wearing very heavy makeup (which is, of course, different in different contexts) and likely also dressed up in quite disparate styles.

Even when you start seeing an abstraction it is very likely that you only see "part" of its nature. Only by seeing it again and again in completely different contexts you start understanding what it really is. You need to familiarise with countless concrete instances before you can really see the nature of an abstraction. But it's very likely that you do not realise this until later. And the moment you "get" the abstraction (or you think you got it) you immediately "switch" the way you see things: you see the abstraction first and the concrete instances as just special cases.
A consequence of this is the monad tutorial fallacy.

But things are even hairier than that: once you switch your mind, you may delude yourself with thinking that you "get" it. It is likely that you only "get" a part of it. And your delusion will hamper your progress by preventing you from recognising instances of that very abstraction that do not "fit" in your partial understanding.
That's when it becomes extremely useful to study what others have done. Other's code will eventually use an abstraction that you already "know" in a context where you would have failed to recognise its usefulness or applicability. And by understanding that code you'll be forced into expanding your understanding of that abstraction.


Mathematics is your friend


I know. This may seem scary. But it's true. Mathematics is not hard and is not your nemesis. Like abstractions it seems hard. But that's because mathematics is, in fact, formal reasoning about abstractions.

You should not be afraid of formal reasoning. In a very deep sense programming is a very formal activity. No matter which language you use you have to be extremely precise and complete in what you "write". When you face programming for the first time it is exactly this necessity of being absolutely precise and detailed, even pedantic, that is "difficult". It's learning to be formal. But it's, after all, not that difficult. It just takes a little practice and patience.

The real difficulty with mathematics is with the abstractions. In fact it's the same kind of difficulty that I described above, except that it's exacerbated by the fact that mathematics is often explained / taught / introduced in a very stupid way.
Very likely you'll be presented with a blanket statement which is a formal definition of something, eventually followed by a list of necessary conditions/properties.

This is even worse than the monad tutorial fallacy! Not only you are given the abstraction before the concrete cases, you are often not given concrete examples in disparate contexts at all. In those cases when you are, they are all stupidly useless (or at least apparently so).
In some sense this is unavoidable: it's impossible to present a concrete case in isolation and make it apparently useful. Even in programming contexts you are often given stupid and apparently useless examples. That's because a
real context is often quite complicated. You do not want to be presented with a 6 weeks programming task only to see how an abstraction that may encompass a total of 3 lines of code (and in some cases even less than one line) is, in fact, useful.
That's why the only way to develop an understanding of abstractions is by writing a lot of code.

By now you are probably thinking that I'm the umpteenth math guru that is trying to sugar the pill. I'm not. I never went to university. My formal education stopped with my high school diploma. For decades I have been programming ignoring pretty much everything about mathematics. I do have a lot of difficulties with everything math (and learning it in my late 40s, while possible, is not as easy as it would have been in my early 20s when my mind was a tad more agile).


You can do it


Unless you are aiming for a PhD in math, you do not have to learn all of it. Most importantly you do not have to study math before you study declarative functional programming. It's the other way around: by programming declaratively and functionally you'll start to recognise the power of abstractions. And you will want to be able to think about them, give them names, reason about them, figure out how they compose and what happens when you do compose them.
You could invent a new name for each of your abstractions, a new term for every conclusion you draw and so on. But you'd be just spending most of your time reinventing the wheel and discovering warm water. Mathematics gives you a language and a formalism to do exactly that. Just do not be afraid of it, and you'll slowly but surely learn how convenient it may be.

Yes, you will face difficulties. Because googling stuff will not give you useful answers: it will only confuse you even more. Most math texts not only assume a lot of pre-existing math knowledge, they also suffer from the above described fallacy: they present stuff in the wrong order and they fail to give you useful "intuition" about things.

Time, practice and a lot of reading is, currently, the only cure I know.
If you stumble upon a text that is beyond your comprehension, try to see how much you do understand. But do not worry: two (or seven) years later you'll probably be able to go back to it and understand far far more. So file that math paper ridden with scary mystic hieroglyphics and magic runes somewhere and be confident that you'll eventually scan it again in the future and actually find it obvious.

See Questions On Quora

Continue reading...
 
Similar threads
Thread starter Title Forum Replies Date
N Study Buddy need someone to learn python together(beginner) Study Buddy 0
R Study Buddy Learn Python together Study Buddy 1

Similar threads

Top