Functional programming is a programming paradigm where programs are constructed by applying and composing functions.
Some of the most popular programming languages include Haskell, Clojure, Scala, Erlang, F#, Rust, etc.
Have you ever tried Functional programming?
Do you prefer it over Procedural or OOP paradigms?
What are some practical examples you have built with it?
Top comments (58)
Let's not forget Python. Python is quite versatile as it has about everything for FP (but also OOP). JS as well.
More on point, I quite like Elixir - which is one step better for FP than even Erlang. I love FP all the way, though sadly it's not promoted enough in my circles :(
JavaScript as well which is a multi-paradigm language
Indeed, very much so
Guido van Rossum was never in support for the functional approach - so I would expect that support would be superficial at best.
The fate of reduce() in Python 3000:
And how can Elixir "be better for FP" than Erlang? Elixir may provide additional creature comforts but that has little to do with FP. Both implement FP as a means to an end, not an end in itself.
Elixir is "better for FP" as an argument to the value of a platform that primarily oriented towards FP. Some arguments against late-day FP adoption are the performance of FP languages (well, less the language itself but the underlying platform). Elixir comes with some improvements, including better use of concurrency (without noticeable performance degradation) under BEAM.
Maybe Guido van Rossum had a thing against FP. But despite that article from 2005, all those functions are faring well in Python. They do what they're meant to do so the support is there. But there's an argument to be had about what it means for a language to be a FP language. Map-reduce (with extended map/reduce/filter) is a pattern. If the language provides the implementation of the pattern, that's great but as long as it can be implemented without productivity or performance penalties, that's fine by me.
Go has nowhere near the same support for FP patterns (oficially) but there are quite a few libraries providing monads in Go. Guess what, it works :)
Both Erlang and Elixir use the same BEAM so there is likely no performance difference. The Elixir compiler would have to produce AST/bytecode that is somehow more efficient than Erlang's output - and I somehow doubt that. The entire point of the BEAM is to create a highly concurrent (and resilient/fault tolerant) operating environment; using FP was motivated by the benefits afforded by "immutability by default" (and consequently persistent data structures) in a Shared Nothing architecture. Even back in a 2014 Talk Bryan Hunter claimed that
… obviously with a fairly limited pool of developers.
One of the more notable improvements in Elixir are hygenic macros - but that has nothing to do with FP.
The "hostility" continues to this day, e.g.:
… and perhaps they all have a point that Python isn't an ideal foundation for "functional programming" - while the occasional "functional tactic/trick" can be helpful.
JS has the advantage that Brendan Eich had Scheme on the brain when he designed it, so it can lend itself to some Scheme-y approaches but JS is still an imperative language as in general neither immutability nor recursion are particularly efficient.
The beauty of algebraic structures is that they are like patterns with superpowers. Implement an algebraic structure to strictly conform to its specific set of "laws" and you get some implicit and powerful benefits.
The problem is that using these implementations without the safety net of a language or environment that yells at you when you start to "break those laws" can get you into trouble when you need those guarantees the most.
Thanks for sharing all this useful information 📚👍
Functions are very expensive in python. The only truly performant python libraries are written in C.
Absolutely, but the subject was more about languages with support for the practice. JS and Python are truly multi paradigm, other aspects notwithstanding. I wouldn't use Python (performance issues mainly) , but doesn't change the point.
Thanks for the input 😉👍
Thank you for sharing your insight 🙏❤
I have tried Haskell and I mostly use it for solving codewars problems
I like it because it's very elegant to write both digitally and physically (on paper) , basically pythonic code on storids
It isn't inheritanly better than OO languages and you probably can implement most features of an object in it
Most people would regard that it is not a very practical language and I would agree,but I certainly improves you as a programmer ,haskell is very inviting as in it invites people to lookup implement of functions often to understand how it works ,on the other hand one can open up standard library and look up implementation in Cpp but it isn't remotely easy to understand
Finally implementing algorithms in Haskell often gives me a deeper understanding of it because you really have to apply your brain to figure every part out .
Haskell has come a long way in making the small, non-practical parts of the language significantly more practical. Modern day Haskell community likes to think in terms of applicatives rather than monads, profunctors and categories rather than arrows, and traversables for composition, instead of monad transformers (in most cases). The unwieldly parts of Haskell, in practical code, really came from an over-obsession on "monads". 10 years ago, that changed. Many of the abstractions have now been made much more modular, separated into a beautiful hierarchy of typeclasses instead of jumbling everything into a monad.
The problem with monads is that they don't compose - leading to deep stacks of monad transformers, which was the only thing that made Haskell "impractical". Everything else has always been very pragmatic even outside of algo problems. I myself use Haskell far more for practical projects than algo problems. I encourage you to give it a shot!
Now, you may have noticed that I just spit out a random bunch of abstract nonsense on the first paragraph. I mean, what the hell is a profunctor? Ok, so the problem with describing programming concepts is that it takes time and most things can't be summarized. This is why those names exist, to summarize them. Except the names mean nothing to people who don't already know the concept. So I'll give you some pointers on practical examples for learning these concepts. They are extremely simple, but I can't summarize all of them in one comment haha.
sequence
function - this is what gives traversable monads compositionality. I love it.There's a whole bunch more really good "modern typeclasses" in the base package now that you should check out. They make practical Haskell extremely elegant and easy to use. Here's a few more that you should check out - Bifunctors, Bitraversables, Bifoldables, Category and Semigroup.
Haskell can also be used in a very pragmatic way :) Check out IHP ihp.digitallyinduced.com/ IHP is similar to Rails/Django/Laravel but has all the powerful advantages of Haskell.
This is interesting, thanks 😉👍
I've heard great things about Haskell from the community 😉
PS I also did codewars challanges couple of years ago, focusing on JS 😀
If doing code wars sounds Fun to you ,not just a way to prep for interview then you will have a great time here
When preparing for interviews I see it as a must, since the problems there are the type you would expect in any technical interview 😉
Tho, as you noted, I was not there for that purpose, tho had a fun time anyway since those challenges are pretty addictive 😀😀
I use FP pretty much exclusively now. But I don't use the category-based variety that is commonly observed in Haskell. What I use in F# is more like typed python. It is very straight-forward. Wrote about it here.
I am also interested in Clojure. I wish for some aspects of its map data structure in F#. I also like the elegance of everything being a list (its lisp-ness). In playing with it, I discovered that at times I need types in my programming. So I'm keeping an eye on Spec to see what happens after alpha. Also hoping Clojure will get ported to .NET Core or whatever MS calls it going forward. (It currently has a legacy .NET Framework port.)
Interesting insight 😉👍
Thanks for the share 🙏❤
I've been spending a lot of time lately working with Elixir. It's a really cool language, and it definitely has me thinking a lot more about recursion and immutability.
I haven't built anything big with it yet, but working in another paradigm has made me question the ways I've been writing code in other languages. I think my JavaScript has improved as a result of me learning Elixir.
Thanks for sharing 🙏❤
I dont rhink Rust is functional
I think it's fair to say rust is imperatively functional. As opposed to declaratively functional. The combination of expression-oriented design, traits (clearly inspired by haskell's typeclasses), a strong focus on safety and minimal mutability, strong typing principles (
Optional
,Result
and such safety oriented control flow encoders - also inspired from haskell), highly efficient iterators which makes them usable in regular control flow (much like haskell) - all of this screams functional programming to me.Though this isn't super special. Throughout the last decade, these very same concepts have been picked up by many modern languages and adopted by older mainstream languages. But since rust started out with all of this - I think it'd be fair to call rust a part of the functional family.
Thanks for clarifying 👍😉
Rust is at the core an imperative language.
However unlike most imperative languages Rust is largely expression based (conditional operator vs. if…else) - this makes it possible to leverage a lot more "functional tactics" in a highly effective manner ("zero cost abstractions") than in other imperative languages.
Thanks for the share, this is insightful 👍😉
Thanks for the heads up 😉
I will leave that for the readers to decide 😉
Functional programming is generally less performant and harder to debug. Functions are expensive unless inlined by compiler. OO is also unperformant due impart to its massive heap use and tendancy to over abstract. Procedural programming, when done properly, will always outperform the other two methods. In my experience, procedural programs are also easier to reason about, debug and maintain. People who flock to oo or functional styles seem to be simply trying to take shortcuts instead of developing a mastery of their craft.
It depends. Most compiled langs can be made performant enough, regardless of their paradigm. But you are correct that over-using certain parts of certain paradigms can certainly slow things down.
However, it's a difficult argument to be made against functional programming. Since the "recent" advancements in FP, from the last ~3 decades of bleeding edge research, has made FP incredibly fast. Haskell, the crown jewel of FP, is ridiculously fast. So much so that it is surprising to people who haven't used FP for a while. Since only a few decades ago - everyone knew that FP was very slow and inefficient.
The reason behind this sudden change, is clear. The papers written on this topic show a clear, strong, and impressive effort in making FP fast. They often lovingly call haskell "25 years of hard work" for papers like these, and it really shows. Incredibly passionate papers like these, demonstrating the strength of formal computer science in practice, is truly refreshing. The best part is that all of this is already implemented in GHC! And research is still ongoing towards greater horizons!
There's more examples of FP being fast other than Haskell (ex: Rust) but I think I've made my point. Moving on to debugging. I suppose it depends? The entire goal of FP is to make things easier to reason about by having formal and pure semantics. Most functions are functions in the same sense as mathematics. There's no tricks and traps. The goal of having "formal semantics" that is "clear to the programmer's eyes" is not unlike the goal of procedural programming. Both do a good job at having explicit semantics. But FP goes the extra way to make functions pure - which truly makes things easier to reason about.
But then, when it comes time to do some impure shenanigans - which is certainly necessary in any practical sense - It may get a bit hairy during debugging depending on what kind of code you write. I myself find it delightfully simple to find exactly what's wrong in my Haskell code compared to, say, my Java/Python/Typescript code. But I also know it is very easy to make non-pure Haskell code extremely difficult to debug (by using outdated concepts). But let's not forget that Haskell is a very extreme example. Many FP languages such as rust, the ML family, clojure actually make it just as easy to debug.
Procedural has the advantage of being foundationally simple with no tricks and traps, which I adore. There's a certain elegance in simplicity that I like. But FP also makes sure that its semantics, even the abstract ones, are explicit and clear - a steep contrast to OOP and its seed of inherent implicit mutability.
This is insightful 👍😉 thanks 🙏❤
Great insight! Thanks 🙏❤
Not for a long time, but back in the 1990s I used both Scheme and Common Lisp quite a bit. My use of Scheme started in an undergrad course on programming language concepts, which was common for PLC courses of the time. Course project involved implementing an interpreter for Scheme. For quite some time after, I'd use Scheme interactively to try out ideas for algorithms even if I'd end up reimplementing in another language afterwards.
In around the same timeframe, I used Common Lisp first in an AI course and then somewhat regularly for AI research.
At the time, I had mixed preferences for either functional or OOP depending on what I was working on.
I haven't really used functional programming much recently other than using some of Java's functional features. But that isn't really functional programming. Mostly OOP with occasional tangents into functional.
Thanks for sharing 🙏❤
I am huge fan and I think every developer should learn it in a language that does it well so that we can become better programmers in all languages. Functional programming is easier to test, reuse, and reason about, according to John Hughes Why Functional Programming Matters. I agree. The more you stick to FP for a good deal of your code in a large codebase in an imperative language the easier these things will be too.
Thanks for the input 🙏❤
I haven't tried full-on functional programming with monads and using the effect type everywhere (like Redux actions, but everywhere).
However, I love "functional-light" programming. This means using function composition, point-free style, map/reduce, recursion and functional utility functions (like the ramda.js functions) where appropriate.
Other things like pure functions, decoupled code, parameterization, etc. are considered clean code whether you use FP or not. So functional programming didn't help me here.
I find it enhances my "normal programming", but doesn't replace it. Sometimes, imperative code is simpler and easier to understand than code using composition and recursion. In the end, that's the important thing. After all, imperative programming and functional programming are mathematically equivalent (so to speak), right?
Maybe after I practice Haskell and monads more I'll find functional programming much better. But that hasn't happened yet.
Thanks for sharing this insight 👍😉
For about a year I'm writing production Java code using style which I call Pragmatic Functional Java. As name suggests, it's based on FP concepts. In particular, monads are used to represent special states. The approach doesn't assume choosing one paradigm over the other. Instead it's a hybrid of FP and OO, where both paradigms complement each other.
Overall, approach works surprisingly well. Code is more readable and significantly more reliable.
Awesome insight, thanks 👍😉