Why you are scared of Functional Programming

kspeakman

Kasey Speakman

Posted on February 6, 2018

Why you are scared of Functional Programming

I remember when I used to hear about so-called "functional programming" (I mean was I doing dysfunctional programming before? Weeeeell, I probably was). I would always come away with the sense that it was needlessly complex. Something only doctoral students were tortured into understanding while they were locked in the ivory tower.

However, since I mostly do functional programming today, I look back at what I could have told Past Me to make him understand that FP is not really intimidating or even reserved for people far-better educated than me. And offer some ways to approach it that setup success.

#1 Don't bother with Monad tutorials

... or other things plucked from Category Theory. You really do not have to know that stuff to start out. One day, Future You may be brimming with confidence which is ready to be destroyed by a Monad tutorial. But for today, such things are interesting "optimizations" that you can learn about later.

It might be hard to avoid getting doused in type theory in certain languages -- I know that you know that I am thinking of Haskell right now. If I were Past Me, I would stick with ML-family languages that do not have heavy type requirements: examples that come to mind are F#, OCaml/Reason, Elm. For you dynamic-type programmers in the audience, those languages also have great type inference so you can omit most type declarations but still get type checking for free.

#2 Pretend you are coming from Procedural Programming

One really common mistake when starting FP is to try to look at everything with the same pair of glasses you used for object-oriented programming. You might try to hide data structures or add methods to data. Well, that's not really the way it works most of the time. You can look at Functional Programming as being more similar to Procedural (done right) than it is to OO. The big differences being that procedural executes side effects all along, whereas FP emphasizes making decisions first and translating those decisions into side effects at the very end.

#3 Don't get obsessed with abstractions

One pervasive problem across all paradigms in the programming universe, is trying to shoehorn too many things into a Theory of Everything abstraction. FP is no different there. In fact, all the Category Theory stuff that you are so afraid of is precisely so you can use a single abstraction against otherwise very different things like a validation results and file IO -- so you can use the same functions on both. That's why I said earlier to consider all that type theory as an "optimization" that you can worry about later.

For now, be okay with observing some duplication of code (e.g. Hmm, there is List.map, Option.map, Result.map... can't quite put my finger on it, but I think some kind of pattern is happening there...) until you are pretty sure it is duplication of the exact same thing, not just something similar.

Sandi Metz said it well:
"duplication is far cheaper than the wrong abstraction"

#4 Cheat on your pure diet a little, if you must

Sometimes it can be really difficult to think about coding a problem without using side effects, because they are so ingrained in my thinking. For example, a tough one for me was generating random numbers. The languages I mentioned above have some escape hatches where you can use side effects if you just get too frustrated and need to move on for now. (Elm itself does not allow side effects, but you can still interop with the ultimate side-effect: JavaScript.)

I also allow myself to use side effects at the "edge" of a program. In a web API I define The Edge as a bad movie from 1997 the "controller". So I might generate some random numbers or get the current date/time or read from the database in the controller. But any decisions I make based on those are in pure functions. Then the decisions that were made go back to the controller, who can turn them into yet more side effects, like saving to a database or loading some more data to use in another pure function. Reminder in case you haven't seen every other post I've talked about FP: being pure makes the decision functions embarrassingly testable and refactorable. Heck I even test all the bad things that can happen as well as the happy path.

#5 Use union types

Raise your hand if you have ever tried to write a class with two nullable properties which were supposed to be mutually exclusive. Example: either some data or an error. This is precisely what union types allow you to represent in a non-awkward way. Learn about them and use them in your data structures.

Did you know that union types are representable in OO languages by using inheritance? But under the OO paradigm it is considered an anti-pattern to do "instance of" checks on an object to get at its implementation details. However in FP it is a good practice to go through all the cases of a union type and perhaps use different functions for each one. Because the emphasis in FP is on functions and immutable data, not object-based abstractions which encapsulate data and methods. Keep that in your back pocket for your journey.

I'm going to let you in on a secret. Don't let this take away from using union types, but that category theory stuff is pretty much centered around them in particular. For now, Past Me, do not taunt Happy Fun Ball always deconstruct union types with case / match statements, and you will keep away from all that type theory. By the time you notice the similarity of it all, you may be ready to go deeper.

After falling in all the traps on my FP journey, hopefully I can point some out to you. ...And accurately speculate on what a better path might have looked like? Eh, accuracy is probably too much to ask. Oh well, I gave it my best go above anyway. :)

💖 💪 🙅 🚩
kspeakman
Kasey Speakman

Posted on February 6, 2018

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related