DEV Community

Cover image for Learn functional programing with me - Part 1 : Language choice

Learn functional programing with me - Part 1 : Language choice

Olivier Guimbal on February 23, 2021

So, I've decided to write a blog. Sure, I could use one of many solutions out there and setup a blog in minutes, but writing a blog is not the mai...
Collapse
 
eriklz profile image
Erik Lundevall Zara • Edited

Another option you may want to consider is F#/Fable.
F# started out as "OCaml on .NET" pretty much and they are quite similar, but not identical. Fable is an F# to JS transpiler.

F# is described as a "functional-first" language, meaning that it is a multi-paradigm language, but the emphasis is on the functional parts.

Learning functional programming (or any type of programming) will not just be about picking a language, but also ecosystem and community.

As you note, ClojureScript is different from the others given that it is a dynamically typed language, while basically, all the others are statically typed languages. It will be a slightly different experience. If your preference is a typed language experience, others will be better. That would exclude Elixir also, which I think otherwise may be a nice option.

If you want to go with the same language for both backend (serverless) and some kind of frontend
my guess is either Purescript or F#.

I have dabbled with Elm and I like it, not server-side rendering though. I am mainly working with backend/infrastructure components. F# works where .NET works - you can use it just fine with AWS Lambda for example, although cold start times are not the best. I have yet to try it via Fable and Node.js runtime with AWS Lambda.

Seems there is at least a sample for F#/Fable for Cloudflare Workers in the Cloudflare docs, so someone there has tried that.

Not tried Purescript yet, on my list ;)

Collapse
 
oguimbal profile image
Olivier Guimbal • Edited

F# is actually the FP-related language I know the best 😁. I did not mention it because Fable feels like it's not taking off (I might be mistaken ?), and because as you mentioned, F# being somehow a bit OO-friendly, I would have a harder time not staying in my comfort zone. Moreover, I find F# abstractions somehow similar, but less powerful compared to Haskell/Purescript (I have a harder time extracting myself away from the imperative paradigm in F#). And I'm a bit attracted to the "pure+immutable by construction" guarantee.

Fable was definitely on my to-try-list, though... Do you have a feedback specific to Fable ? Have you tried it ? Do you have an opinion/advice on which libs to use ?

Regarding cold start times: If what you're trying to do is not computationally heavy (i.e. runs in less than 50ms of CPU time - excluding idle time when waiting for requests), and if the language you're using compiles to something that can be ingested by V8 (Javascript bundle/WASM) I'd strongly recommand Cloudflare Workers over Lambda: CF workers have a near zero cold start, and they are waaay cheaper ! Their approach is actually pretty clever: They dont spawn a whole isolated process (which has a lot of overhead), but rather execute each request in a V8 isolate.

Collapse
 
eriklz profile image
Erik Lundevall Zara

To go full force into learning pure FP, then Haskell/Purescript is likely better. F# is perhaps not "taking off" in terms of widespread adoption, but I do not think you will get that with Haskell/Purescript for web app/serverless solutions either. I see F# as being more pragmatic than pure.

My hands-on experience with Fable specifically is very limited so far, unfortunately.
Cloudflare workers would have been useful if it was edge computing and not needed to be within the realm of the AWS ecosystem, e.g. running within VPCs, integrating with other AWS services. For a lot of these use cases though, a bit longer cold start is not an issue.

Thread Thread
 
oguimbal profile image
Olivier Guimbal • Edited

+1 on the "more pragmatic than pure" part 😊

Dont get me wrong, I dont care working with a language that has a small community (I wouldnt explore FP, if I did). By "not taking off", I meant that I've not seen as much learning resources about Fable as for the others (and I was specifically thinking about Fable, not F#).

Collapse
 
jwp profile image
John Peters • Edited

I get confused when studying this stuff. To me, if they don't integrate easily with JavaScript for client side consideration, then my front end work will never use them.

I do understand how Microservices can change all this. But do I really want to learn a new 'framework'? I already know 4 languages, 2 major front-end frameworks, 1 major back-end framework, SQL, GraphQL, parts of Azure, and 3 Styling Frameworks.

My feeling is that the functional languages have a low priority on my radar. I studied F# when it first arrived, read all the hoopla and ultimately rejected it due to my mistrust of MSFT and lack of ambition. All these years later, I don't see the amount of job openings in F#, Haskell, OCAML, ELM, or the rest; anywhere near current web technologies.

Collapse
 
oguimbal profile image
Olivier Guimbal • Edited

Nobody is forcing you to learn such languages if you feel you dont need to 😊
That said, saying "I know how to code, so why learn more ?" feels a bit like saying "I know how to read, so why read more ?". It doesnt leave much room for improvement.

Learning about other paradigms or technologies (not necessarily FP) really is game changing. You should try it. It allows you to broaden your sight, think differently, and will enventually help you write better code, even in non FP languages.

Your point about job openings is somehow misleading... while it is true that there might be fewer FP job openings, it does not mean that there are none: They just tend to be more qualified job, as you could infer from stackoverflow survey.
But even ignoring this fact... it's not about getting a job to me (I dont care about having more jobs, I already got multiple ones), but rather about self-improvement.

ps: Almost all languages listed in this article integrate easily with Javascript. And tend to be much more reliable (which is not hard, when speaking of Javascsript !)... which means a better experience for your customers.

Collapse
 
jwp profile image
John Peters • Edited

I must not have communicated my feelings well enough. What I'm saying is that I do not see FP experience on my resume as a game changer.

In January; I went through 90 interviews for a Senior Level Position. Not one person ever asked anything about ELM, F#, Closure, OCAML, or the rest.

What they wanted was top to bottom experience from specific things like Typescript, JavaScript, React, Angular, Devops Pipelines, Microservices, SQL, NoSQL, GraphQL and either Node or ASP.NET for backends.

I'm also not indicating that I reject learning it, rather that it is just low on my priority list, that's all. I look forward to reading more about your experiences and hope this is the start of a series that changes my mind.

Thread Thread
 
oguimbal profile image
Olivier Guimbal

Oh right, I understood it the other way around... I'm French, so that happens 😁

Opinion ahead... nobody is asking you about it because they dont know about it.
And few people are humble enough to tell when they dont know... especially in asymetic situations such as interviews, when the interviewer is supposed to "know better", for some absurd reason.

I've interviewed a fair share of candidates, and not seen much who had FP experiences... I'd definitely give some bonus to those who do speak about it.

That being said, FP is slowly, but steadily gaining traction, and I believe those who will know about it will have an easier time dealing with the future.

For instance, several TC39 propositions are about integrating typically FP features into Javascript (such as this or this)

Thread Thread
 
jwp profile image
John Peters

I'm looking forward to reading your series on FP. Thanks!

Collapse
 
kspeakman profile image
Kasey Speakman

Another vote for F# with Fable/Elmish here. It is what we use for all new projects. And before that we were using Elm. Both use the Model-View-Update pattern which is both a great trainer on pure functions / functional programming and amazing to work with long term.

Collapse
 
kspeakman profile image
Kasey Speakman

Also note that Fable/Elmish implicitly includes React for DOM rendering, so you can take advantage of some of its features like SSR. However dev-facing Elmish code does not use the React component programming model by default, since it does not exactly align with MVU. You can opt into some React component features it if it makes sense for your problem, but we never do since it makes it more object-like. We like composing data separately from functions where components force you to compose along 2 dimensions at once. I also have this post about keeping it simple in F#.

Collapse
 
oguimbal profile image
Olivier Guimbal

I will check that, thanks :)

Collapse
 
bdunn313 profile image
Brad Dunn • Edited

Just wanted to point out that the ReasonML issue that you brought up is valid... which is why the community said "We need to fix this!" and ended up creating ReScript!!!

rescript-lang.org/

Basically, ReScript is an effort to say "Yeah... this was confusing. Forget the rest and just focus on this piece, this is all you need".

Check it out... most of the downsides just disappear with this new direction, and the syntax is even closer to Javascript! Highly recommended, but I'm a fanboy so that's my disclaimer.

Collapse
 
oguimbal profile image
Olivier Guimbal

Haha, looks a bit like:

Collapse
 
bdunn313 profile image
Brad Dunn

LMAO! Hopefully not! It seems like the community is in fact consolidating around ReScript, but... point taken!

Collapse
 
sirseanofloxley profile image
Sean Allin Newell

I think its actually quite easy to sidestep OOP and 'impurities' when writing F#. Digging into mutable code/streams/low levels feela very similar to writing bad C# code to me. You just know somewhere inside that it's wrong or not as elegant or not maintainable. I've built type safe SQL apps in F# (checked against sql schema!!), ETLs, web apps, front ends... All the things.

Vote for F#!!

Collapse
 
oguimbal profile image
Olivier Guimbal

I agree... it feels wrong, like you said, but the fact that it is possible is a danger when the lazy me is lurking around 😁 In perticular, the fact that Classes & mutable states are easy to write does not force me out of my bad habbits.

Anyway, that's a lot of votes for F#, I definitely did not expect that ! I'll take it into account.

Collapse
 
peerreynders profile image
peerreynders • Edited

What do you think ?

While Elm is easier you are tied to it's implementation of a VDOM and are essentially tied to CSR (client side rendering).

So ReScript is a good choice - just think long and hard whether you want to go down the React rabbit hole (granted others have already paved the way but using a different framework could be seen as an opportunity to practice interop (which frankly is no picknick in Elm either)). I find "the mess" of ReScript is only skin-deep; it's essentially OCaml streamlined for a JavaScript runtime - the Reason-style syntax muddies the waters a bit to be more appealing to JavaScript programmers (Introduction to Functional Programming in OCaml is a good introduction to OCaml).

Have I forgotten a FP language that you love and would like to be considered ?

Well, the core of the problem is that you want to build something ASAP. But when you build stuff you will invariably relapse into old habits and that will prevent you from actually learning FP. So I think it's more important to get into the habit of thinking in FP first, i.e. getting away from thinking in terms of manipulating the flow of control and moving towards using data transformation as a means of processing.

One approach would be to work through the exercises in Haskell Programming from first principles - but even here Haskell makes things harder than they need to be as on top of everything else FP, it imposes uncompromising purity and laziness by default. With something like Erlang you can get into the processing by data transformation mindset without all that other hassle.

And while PureScript drops laziness it likely has the weakest ecosystem of all the options that you listed.

I personally got into FP via learning Clojure and doing 4clojure exercises. But at the time I was already familiar with the Java ecosystem - so I was already acclimatized to its idiosyncrasies (but by all means watch all of Rich Hickey's talks like Simplicity Matters and Value of Values).

Given that there is a lot of unlearning that has to take place it may be a good idea to start from the beginning:

How to Design Programs, Second Edition

To be clear this doesn't teach Racket (formerly PLT Scheme) but it uses five constrained student languages to convey certain concepts in a very focused way.

An Anecdote

And after having successfully adopted an FP-way of thinking it should be much less of a problem to become quickly productive in something like ReScript in an FP-way.

PS: there is also Js_of_ocaml

Collapse
 
oguimbal profile image
Olivier Guimbal • Edited

I wouldn't say that I'm trying to build something ASAP, rather than I now feel that it is time I stop reading the endless stream of books and tutorials that try to make me learn the FP way, and start building actual stuff with that knowledge (not only hello worlds or katas, which are mostly useless when it comes to learning the real world). I've read several books on FP so far, countless tutorials and articles (which were essentially introducing concepts & syntax... not "how to build stuff"), developped a complete fluid dynamics simulator and various linear algebra tools in F# (that was a big project, but that is almost pure maths, it doesnt count as "real world stuff" to me), followed advent of code 2020 with Haskell, spent dozens of hours browsing code and toying with several FP languages. So I wouldn't say that I'm not somewhat acquainted with FP principles, and I have been actually often applying them in non FP languages for a while now (immutability, pure functions, completeness, data-oriented design, ...)

Thanks for the talks links. I already saw one of those :) What made me dive into FP is also Clojure, Rich Hickey talks, and Richard Feldman's (this one is emblematic to me).

My ambition here is not to learn the FP way... That's the backbone of most of the books/tutorials I found, and I've been reading about it ad-nauseam. I'm under the impression that FP developpers get a bit obsessed about how different FP is, and how important it is to ingest this paradigm shift fully... yea, well... I get that. It IS seductive. But couldn't we learn also how to do things with it, before mastering the FP way ? By mostly emphasising theoretical stuff, I think (at least that's my case), that it can lead begginers to some kind of fatigue. How would you prevent people from switching back to concepts they know when you dont give them the impression that they are about to be able to build something ?

When you browse the internet... you'll find dozens of testimonies like "Yea, I've been trying to learn Haskell... 5 times", they're typical. Why do you think that is ?

If I may risk a dubious metaphore: FP is to OO what DVORAK/BEPO is to QWERTY/AZERTY... you know it is better, and it would perhaps be easy to learn it straightaway. But once you know QWERTY, you could pratice BEPO the right way with exercice for ages and never get it. If you really want to adopt it someday, you'll have to stop theoretical excercice, and start practicing on real stuff. Otherwise, there will never be a day when you will wake up and say "okay, I'm now better with a DVORAK than I am with a QWERTY" ... it just won't happen. I dont say learning theory is usless, far from it, but there is no real point in learning too much theory straightaway IMO.

Collapse
 
peerreynders profile image
peerreynders • Edited

or katas, which are mostly useless when it comes to learning the real world

Perhaps the katas you chose weren't focused enough on training specific aspects of the FP mindset.

countless tutorials and articles

I've been noticing that the signal to noise ratio is currently on a steep downward trend when it comes information on the web. The "learn by teaching" meme has gone too far as there are countless authors posting content on topics they have barely a grasp of - often making statements that are incorrect.

often applying them in non FP languages for a while now (immutability, pure functions, completeness, data-oriented design, ...)

That's another one of those cliches. In my judgement it's much harder to grasp FP by practicing an "FP-style" in a non-FP language - I'm going as far as stating that in many cases it doesn't work. Practicing an "FP-style" in a non-FP language after having been confined long-term in an "FP jail cell" is a totally different ballgame.

data-oriented design,

What does data-oriented design have to do with FP?

For 10+ years that has been a style that optimizes code and data organization for hardware (caches) which lead to Entities, Components, Systems and currently HPC# and DOTS (other resources) - it's highly place-oriented and embraces mutability.

Thanks for the talks links.

There are plenty more.

and Richard Feldman's

The one I keep going back to is Scaling Elm Apps because he implicitly explains how the notion of a "component" doesn't work in FP. In the From Rails to Elm and Haskell he explains how NoRedInk arrived at using Haskell on the back-end. And for him this progression makes sense. In 2014 he published "Developing a React Edge" and it was some time after that when he tried Elm at NoRedInk. Elm was designed to be more accessible than Haskell and for years Elm was used at NoRedInk while Rails was running the back-end. With all those years of "Elm familiarity" the transition to Haskell would be much easier than back in 2014 (Make Data Structures is another good one).

My ambition here is not to learn the FP way.

But your title states "Learn functional programming with me" - how do you plan to practice functional programming without the "FP way"???

I'm under the impression that FP developpers get a bit obsessed about how different FP is, and how important it is to ingest this paradigm shift fully... yea, well... I get that. It IS seductive.

I think you've been hanging around the wrong Haskellers and/or Lispers. Of course you'll find fundamentalists out there but the principle is that the fastest way to "get FP" is to be completely cut off from the familiarity and comforts of OO and imperative programming and to work under full FP constraints (which doesn't necessarily mean Haskell). However under these types of constraints it becomes quickly clear that "building something" is an incredibly complex affair because you are stripped of your usual skills that you have come to unconsciously rely on - you're essentially a beginner again - and worse - you "know how to program" but here you are "learning to program all over again" which can be incredibly frustrating. That's why there is an emphasis on exercises (and lots of them) that are highly constrained and that have a particular theme - largely to keep the student from being overwhelmed.

Clojure helped me "get it" because it was very clear that "I wasn't in Kansas anymore"; parentheses everywhere and I was completely cut off from doing things the "usual way" (but not to the extreme that Haskell forces on you) - in hindsight I think any Lisp or Scheme (e.g. Racket) would have worked.

But from what I know now, I think that if you already program, Erlang is the fastest way to find your FP-feet, while it doesn't have the prettiest syntax it doesn't induce "parentheses-phobia" and it's a small language that should be relatively easy to learn - and finally in Erlang FP isn't a goal but a means to an end. (To somebody who only knows JavaScript or Python I'd likely recommend the HtDP/Racket route; for people learning to program PaPL/Pyret might be better.)

Francesco Cesarini - when learning Erlang:

  • The first hurdle is pattern matching.
  • The second hurdle is understanding recursion and the whole concept of tail recursion versus non-tail recursion.
  • And the third kind of hurdle is thinking concurrently.

Now that last one is particular to the BEAM but using recursion instead of iteration is a common theme in FP, knowing the difference between tail (last-call) and body recursion and knowing how to convert body recursion into tail recursion.

Pattern matching is also commonly found in FP and used for a significant portion of conditional expressions.

Other hurdles that are worth mentioning are (obviously) immutability and (less obviously) thinking in terms of expressions instead of statements.

Thinking like an Erlanger

Now for "building stuff" many people will recommend Elixir over Erlang. The trap here is that the Ruby-like syntax will lead some beginners to persist with an imperative approach. Now fortunately Saša Jurić's Elixir in Action 2e steers well clear of that and knows how to effectively introduce Elixir/FP to OO-trained developers (on a more fundamental level Learn Functional Programming with Elixir is supposed to be good as well).

Why do you think that is.

My personal opinion is that Haskell is simply too high a bar for most people starting from imperative OO - at least it was for me (I'm simply a Haskell tourist, it's a nice place to visit every now and then). And as I was alluding to in my first comment, immutability and pure functions are hard enough but piling on laziness and static typing with higher-kinded types (which Elm dropped for that reason) is just too much. So I'm not surprised that Haskell can take people multiple attempts.

FP is to OO what DVORAK/BEPO is to QWERTY/AZERTY.

Typing is a much less complex endeavour than designing and writing software. Now take the agony you feel being forced to use that Dvorak keyboard for the first time (all day) after being proficient with QWERTY and amplify that by several magnitudes - that's what it feels like trying to "build something" in Haskell without a change in mindset because it involves a completely different set of problem solving skills.

I suppose F#, similarly to Scala, suffers from the curse of multi-paradigm languages - while they are meant to provide the "right tool for the job" they end up largely supporting the developer with a familiar way of doing things even when it is sub-optimal for the problem at hand. I've tried several times since its first appearance in 2005 to get into F# but at no time felt that it helped me along my FP journey.

Now clearly it can be done as Scott Wlaschin always demonstrates (F# for Fun and Profit, Domain Modeling Made Functional) but my feeling is that OCaml makes it much easier to stay on the FP side of things.

Mark Seeman is another personality of interest (From dependency injection to dependency rejection, Functional architecture - The pits of success) in this space - he often compares F# and C# approaches and F# and Haskell approaches.


Here is an example of a project that switched from Elm to PureScript: Building a Graphical IDE

The kicker is that they didn't build on that experience - for a later project they went back to static HTML, SVG, JavaScript, and D3.js: Visualizing Home Automation with GRiSP

Note the Phil Freeman retired as a PureScript maintainer back in 2017.


These Modern Programming Languages Will Make You Suffer

Collapse
 
etienneburdet profile image
Etienne Burdet

I doesn't qualify as serverless or SSG, but I would suggest Exilir with Phoenix! It has all you want from a modern high level language (and then some), it's super fast and it's built on the rock solid Erlang OTP.

Doing backend only in node may seem easier at first, but in the long run it can lead to cumbersome architecture. Starting with plain old server-side MVC is always a safe choice.

Collapse
 
oguimbal profile image
Olivier Guimbal • Edited

I've hesitated to put Elixir on this list (a friend of mine suggested the same thing)... it did not make the cut because I barely know it: I've only read about it, never actually tried it. But I think I will.

Collapse
 
peterstorm profile image
Peter Storm

I just want to say that the miso framework in Haskell has the ability to do isomorphic apps - it's Elm inspired, but has all the power of Haskell, because... well, it is Haskell :D

You need to learn a bit of Nix though, which is it's downside.

Collapse
 
oguimbal profile image
Olivier Guimbal

Ah ! Finally an Haskell lib that has a nice documentation. (see my rant about that here). I will definitely check it out.

Collapse
 
oguimbal profile image
Olivier Guimbal • Edited

That said, leverages GHCJS. If I understood right, it is often blamed to generate huge js bundles. That also is a downside 😑

Collapse
 
peterstorm profile image
Peter Storm

Yeah, but there's alot of things you can do to mitigate that, like using the closure compiler, etc. And I think there's benchmarks against alot of other compile to js frameworks, regarding both performance and bundle size, and as I remember it's great performance wise, and a liiiiiitle behind size wise.

Collapse
 
climbing_dev profile image
Maciej Modzelewski

Hey Oliver, thanks for sharing! I've also started getting into functional programming recently and I chose Scala as the language to learn (but same as F# this is not a pure functional language). If you choose Haskell you might want to check out: learnyouahaskell.com - this is a very good introduction of the language, starting from the very basics.
Good luck and maybe we can do some collab further down the road about our learnigns :)

Collapse
 
oguimbal profile image
Olivier Guimbal

Hi ! Thanks for the link 😊 I already read it, but it is definitely worth mentioning... it is really nice to grasp the "why", but definitely not the "how". It lacks a bit of hands-on material, if you ask me (once read it, you will not have a clue how to start writing a server, for instance).

Collapse
 
dbeardionaire profile image
David Beard

Love using F# type providers in notebooks for random data exports. You can also use pretty much all of the libraries in the .net eco system to support your projects... Although one day I want to learn Haskell but don't have the time to reassemble my brain right now.

Collapse
 
zacharysarette profile image
Zach

Why not Scala?

Collapse
 
oguimbal profile image
Olivier Guimbal • Edited

Mostly because I had to choose, because I dont know it that much, and because it struck me as a language that compromises a bit too much between OO and FP to be a good language to dive right in.

But I might be wrong, and I have nothing against Scala :)

Collapse
 
zacharysarette profile image
Zach

Fair! :)

Collapse
 
paras594 profile image
Paras 🧙‍♂️

This will be interesting to follow !! :)...all the best !

Collapse
 
bjorngrunde profile image
Björn Grunde

If you want client-side as well, consider Elixir. It is a server-side language that is extremely powerful and it has a server-rendered interactive front-end called LiveView. This means you can write server-side code that updates the front-end in realtime, it is concurrent out of the box and proved to be able to manage millions of users per node. The only con is that you cant do offline apps ofc.

But seriously check out Elixir LiveView on youtube.

Collapse
 
nima__ profile image
Nima

Interesting topic , FP is my favorite approach , Have you ever tried Elixir? It's too easy
to learn ( however some parts of it needs erlang syntaxes )

Collapse
 
oguimbal profile image
Olivier Guimbal

Did not know it... another lisp. How does it compare to Clojure to you ?
That said, it doesnt seem to be a good fit for frontend development, is it ?