DEV Community

Cover image for Have you tried functional programming?
Madza
Madza

Posted on

Have you tried functional programming?

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?

Discussion (58)

Collapse
andreidascalu profile image
Andrei Dascalu

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 :(

Collapse
joelbonetr profile image
JoelBonetR

JavaScript as well which is a multi-paradigm language

Collapse
andreidascalu profile image
Andrei Dascalu

Indeed, very much so

Collapse
peerreynders profile image
peerreynders • Edited on

Python is quite versatile as it has about everything for FP

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:

Most Python users are unfamiliar with Lisp or Scheme, so the name is confusing; also, there is a widespread misunderstanding that lambda can do things that a nested function can't


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.

Collapse
andreidascalu profile image
Andrei Dascalu

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 :)

Thread Thread
peerreynders profile image
peerreynders

Elixir comes with some improvements, including better use of concurrency (without noticeable performance degradation) under BEAM.

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

60% of the world's mobile traffic is going through Erlang

… 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.


all those functions are faring well in Python.

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.


there are quite a few libraries providing monads in Go. Guess what, it works :)

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.

Thread Thread
madza profile image
Madza Author

Thanks for sharing all this useful information πŸ“šπŸ‘

Collapse
peter_brown_cc2f497ac1175 profile image
Peter Brown

Functions are very expensive in python. The only truly performant python libraries are written in C.

Collapse
andreidascalu profile image
Andrei Dascalu

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.

Collapse
madza profile image
Madza Author

Thanks for the input πŸ˜‰πŸ‘

Collapse
madza profile image
Madza Author

Thank you for sharing your insight πŸ™β€

Collapse
jayantc89319020 profile image
Jayant

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 .

Collapse
totally_chase profile image
Phantz

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.

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.

Collapse
mpscholten profile image
Marc Scholten

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.

Collapse
madza profile image
Madza Author

This is interesting, thanks πŸ˜‰πŸ‘

Collapse
madza profile image
Madza Author

I've heard great things about Haskell from the community πŸ˜‰
PS I also did codewars challanges couple of years ago, focusing on JS πŸ˜€

Collapse
jayantc89319020 profile image
Jayant

If doing code wars sounds Fun to you ,not just a way to prep for interview then you will have a great time here

Thread Thread
madza profile image
Madza Author

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 πŸ˜€πŸ˜€

Collapse
kspeakman profile image
Kasey Speakman • Edited on

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.)

Collapse
madza profile image
Madza Author

Interesting insight πŸ˜‰πŸ‘
Thanks for the share πŸ™β€

Collapse
brewinstallbuzzwords profile image
Adam Davis

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.

Collapse
madza profile image
Madza Author

Thanks for sharing πŸ™β€

Collapse
hamidb80 profile image
hamid

I dont rhink Rust is functional

Collapse
totally_chase profile image
Phantz

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.

Collapse
madza profile image
Madza Author

Thanks for clarifying πŸ‘πŸ˜‰

Collapse
peerreynders profile image
peerreynders

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.

Collapse
madza profile image
Madza Author

Thanks for the share, this is insightful πŸ‘πŸ˜‰

Collapse
madza profile image
Madza Author

Thanks for the heads up πŸ˜‰
I will leave that for the readers to decide πŸ˜‰

Collapse
peter_brown_cc2f497ac1175 profile image
Peter Brown

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.

Collapse
totally_chase profile image
Phantz

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.

Collapse
madza profile image
Madza Author

This is insightful πŸ‘πŸ˜‰ thanks πŸ™β€

Collapse
madza profile image
Madza Author

Great insight! Thanks πŸ™β€

Collapse
cicirello profile image
Vincent A. Cicirello

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.

Collapse
madza profile image
Madza Author

Thanks for sharing πŸ™β€

Collapse
mmachenry profile image
Mike MacHenry

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.

Collapse
madza profile image
Madza Author

Thanks for the input πŸ™β€

Collapse
sargalias profile image
Spyros Argalias • Edited on

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.

Collapse
madza profile image
Madza Author

Thanks for sharing this insight πŸ‘πŸ˜‰

Collapse
siy profile image
Sergiy Yevtushenko

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.

Collapse
madza profile image
Madza Author

Awesome insight, thanks πŸ‘πŸ˜‰

Collapse
theonlytails profile image
TheOnlyTails

I use it all the time when creating DSLs with Kotlin. By having higher-level functions, extension function and lambdas with receivers, you can make some very cool syntax. I detail more about it here: theonlytails.com/blog/data-goblin

Collapse
madza profile image
Madza Author

Thanks for the share! πŸ™β€

Collapse
anar1996 profile image
Anar • Edited on

Oop,is the best paradigm among all programming concept.
You can easily write code here, and if you have a good way of thinking in real life, you can develop algorithms in a great way by transferring them to coding.

Collapse
madza profile image
Madza Author

Thanks for the input πŸ‘πŸ˜‰

Collapse
anar1996 profile image
Anar

For example, whenever I want to write code or when I am stuck, I always think about how this happens in real life. Then with some of my software basics (variable,loops,arrays, and etc.) I pass them into code so I'm glad I wrote nice code and made something that works.

Collapse
anar1996 profile image
Anar

My pleasure

Collapse
shvahabi profile image
Ψ΄Ψ§Ω‡Ψ―

Scala is the only real solution for FP, other languages are either just mix and hence mess up with FP with OOP such as python or Javascript functional capabilities; or are pure functional and hence almost useless except in academia such as Haskell. But Scala under the hood, solved many problems, to become a practical object-functional language. Scala is not just a new syntax plus compiler, it's a collection of new ways to speak to computers, you will find any language phenomena in Scala and once you learn it, it will be canonical to your programming thinking.

Collapse
fareez profile image
Fareez Ahamed

I like FP. But on the other hand OOPs strong position in software development is not an accident. We have benefitted a lot from Encapsulation, Abstraction especially when many teams work on parts of large application. I still couldn't visualize the same happening with FP where 100s of developers work together for a product across multiple teams. Maybe it's because of my lack of experience with large projects on FP.

With OOP I think its easier to consume libraries without knowing too much detail under the hood. It could be one reason for the huge ecosystem that Java OR Dotnet produced.

However, more and more functional features will get into the mainstream languages like Java and C#. Already it's happening.

I think successful future languages will be combining the features of OOP and FP in right proportion. Success and adoption of Rust is an example. Rust makes a nice balance of OOP features and FP features.

Collapse
madza profile image
Madza Author

Great insight, thanks πŸ™β€

Collapse
lucamug profile image
lucamug
Collapse
madza profile image
Madza Author

Thanks for the share! It's an awesome read πŸ‘πŸ“š

Collapse
peerreynders profile image
peerreynders

I like differentiate the paradigms on a much more fundamental level:

Imperative programming describes the "flow of control" (think flowcharts) where program execution moves computation forward by manipulating values in place (PLOP - Place-Oriented Programming)

Object-Oriented Programming is a flavour of imperative programming where the "description" is partitioned into a set of classes, each responsible for the initialization of data instances (objects) while also collecting the functions (methods) relevant to the management of these data instances. Ideally these classes are"discovered" by exploring their collaborations and identifying their responsibilities (CRC).
While conceptually method calls are often seen as "an object receiving a message" what really is happening is that program execution (flow of control) moves computation forward along the method calls between collaborating objects whose behaviour is largely governed by their own mutable data.

Functional Programming advances computation by creating new values through the transformation of existing values (value-oriented programming). A functional program's description focuses of the "flow of values" (not to be confused with dataflow programming) rather than the "flow of control" .

When learning functional programming my personal advice is to avoid doing so in a multi-paradigm language - familiarity-bias will tend to push you towards solving problems in the way you already know how, undermining the learning effort.

Also in my observation when "learning to program" it seems to be easier to transition from functional to imperative rather than the other way around (which doesn't imply learning to program in a functional way is inherently harder - it's just that the imperative way of thinking can get in the way, so it has to be "unlearned" first).

  • For just gaining FP experience have a look at Racket. The 5 Student Languages of How To Design Programs 2e were created with it. It comes with the DrRacket Programming Environment. One warning though - it may initially require battling some parentheses-noia. Typically it's worth sticking with it - though occasionally the unthinkable happens (ultimately this lead to pyret being developed as a teaching language; DCIC). The Little Schemer, 4e; Realm of Racket

  • If you already have experience with the idiosyncrasies of the Java ecosystem then Clojure is another option. However the same "parentheses-phobia" caveat applies here. I would not recommend Scala as it suffers from the "multi-paradigm curse". In this particular case the community includes two factions: "I'd rather be programming in Haskell" vs "A better Java". It's beneath the former to deal with the code of the latter while the latter couldn't deal with the code of the former even if they wanted to - this is code written in one and the same language!
    I imagine that the risk could be mitigated by working through Functional Programming In Scala but from what I've heard that is quite a slog (companion).

  • If you're interested in transpilation and don't mind fiddling with some tooling, check out ReScript. It's essentially OCaml dressed in JavaScript's clothes. Now OCaml has plenty of imperative escape hatches but it's pretty clear when you let the mantle of FP slide. Keep an eye open in case there is another run of the OCaml MOOC.

  • Another one to watch for is Functional Programming in Erlang

Collapse
madza profile image
Madza Author

This has to be one of the most most insightful replies I've readπŸ’―βœ¨
Thanks for taking time to share your insights πŸ™β€

Collapse
abolarin profile image
Ebenezer Abolarin

Hi everyone,
I am Eben, I am new to programming and software engineering, I am keen and here to learn from the expert in the house. I am here to also learn the industry best practices.

Thanks

Collapse
madza profile image
Madza Author

Welcome to DEV πŸ™β€
Lots of awesome folks in this community πŸ˜‰πŸ‘

Collapse
xowap profile image
RΓ©my πŸ€–

Not per se, but I definitely use that paradigm a lot in the context of Vue. Computed properties are definitely an amazing new(-ish) way of rendering front-ends!

Collapse
madza profile image
Madza Author

Thanks for the share! πŸ™β€

Collapse
justummar profile image
Justummar

I don't know what it is? And why it is?