DEV Community

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

Posted on

Learn functional programing with me - Part 1 : Language choice

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 main purpose here (who gives a πŸ’© about my opinion anyway ?).
I'd like to learn a language AND build something while doing so.

If you're interested, I'd like this to be collaborative in some way: You could comment my choices, learn from them, and influence them (for instance, you can today influence the language I will use - see below).


πŸ€” Why would you care ?

TLDR : I will explain, step by step, how I built it, and I will post all the resources that I used to learn how to do it along the way.

In my (relatively) long experience, I learnt and used on real projects many languages that could be qualified as imperative more than functional languages, such as Javascript/Typescript, C#, Dart, Java, VB, C++ (non exhaustive list).

I've always been toying with FP languages, but never had the oportunity to use them on an actual project, so I've decided to build a blog using one of those.

If like me, you already know imperative languages, but you're interested by learning a functional language, you might want to stick with this series.

It aims experienced developpers with at least a little bit of awareness about FP concepts.

Being myself a semi-begginer in most FP languages, you will probably learn the language progressively with me, see (and discuss?) my architectual choices, my mistakes, my misunderstandings, and the solutions I came up with.


πŸ€ͺ Why do I do that ?

My goal here is to write a tutorial which is progressive, and hands on.

I'm tired of reading hundreds of attempts of guys who already got it to teach category theory by the menu, because they think that their approach at teaching it is better. Reading those, I've been admitedly learning a lot, but I feel incapable of building an actual project with all that knowledge. Which seems retrospectively crazy to me... I don't recall having this kind of feeling when learning simple non FP languages.

When it comes to learning, I believe practice is better that theory to begin with, and that learning practice with someone is better that learning it from someone. Even if it means not learning things the academic way.


🎯 Specifications - what should it do ?

Here is what I'm expecting it to do:

  • To be server-side rendered (for SEO) - so no client-only/SPA stuff.
  • To be serverless, and to be served via a CDN, zero fixed cost (if possible via Cloudflare Workers, because I πŸ’– them.. if not, via some kind of Lambda@Edge or equivalent, or even some kind of FAAS + github pages... why not ?)
  • To have a git repository containing .md files as raw source (I don't want any online editor, authentication system, or other πŸ’©) - will probably be implemented using hooks/github actions which will update the actual blog.
  • To have multiple blogging categories (tech, opinions, ...), presented as columns on the landing page.
  • To support multiple formats: tweet-like, pictures, videos, articles (to begin with)
  • To automatically repost articles I'm writing on various medium (dev.to, medium.com, reddit, twitter, mastodon, ...), and if legally and technically possible, show the associated comments/likes/claps/retweets/etc on the main blog.
  • To be written using FP language(s)

πŸ‘… Language

So, I must say, I've toyed a lot with FP languages, thinking that at one point, one of those might strike me as "the best for my needs". That did not happen. Instead, I got lost along the way, learning a little bit about each one, but never mastering any.

Here is a non exhaustive list of the languages that I considered:

  • 1️⃣ Purescript
  • 2️⃣ ELM
  • 3️⃣ ReasonML/ReScript
  • 4️⃣ Haskell
  • 5️⃣ Clojure(Script)

Below is my perception about each one of those.

As of writing this article, my curiosity about Haskell or equivalent would make me choose Purescript (I'm not settled on the UI lib to use).

If you'd rather see me write it in another of those languages, please comment, I might (or might not) be convinced or influenced , and take your choice into account 😊

1️⃣ Purescript

Purescript is a child of Haskell (their syntax are almost identical), targeting mostly Javascript.

βœ” PROS:

  • Pure FP Purescript is a pure functional language. This seems to bring a lot of liberties and guarantees while reasoning about your code.
  • Interop: It outputs quite readable Javascript, and has a very clean FFI (meaning that you can interact with existing Js code/libraries very easily).

  • Client+Server:It is usage agnostic, meaning that it can be used both server-side (running NodeJS), and client-side

  • Typing: I've only explored a bit of them, but Haskell-like type systems seems soo smooth, and leads to elegant implementations.

πŸ’₯ CONS:

  • Learning curve: This is no little thing, it is a "next-level" programming language. Meaning that the concepts that you can play with are so much more powerful and advanced that your brain will hurt by learning it. A single line of code can hide much more meaning compared to a classic language, which always make you wonder if you got it all, when reading code. Seems to worth it, though.

πŸ“š Framework:

My first exploratory work would point at either purescript-halogen or purescript-elmish.

Halogen seems nice and widely used, but its SSR story is less clear. On the other hand, Elmish has the advantage of kind-of learning Elm along the way, but is less used (then, there will be less learning resource).

2️⃣ ELM

Like Purescript, Elm is also a child of Haskell, but much more simpler. It actually feels like a simplification + specialization of Haskell, bringing more guarantees on the table, along with a much more nicer syntax error messages.

βœ” PROS:

  • Pure FP ELM is also a pure functional language.
  • Safety: ELM proudly guarantees near-zero runtime exceptions. Meaning that it is literally impossible to encounter any runtime error with ELM (except inevitable things such as out-of-memory & stack-overflow errors). It obviously does not imply that you cannot write errors in your logic, but it means that if it compiles, it will not crash.
  • Error messages: ELM is very well known to have state-of-the art syntax error messages. They seem useful, pointing at solutions/suggestions/useful links.
  • Bundle sizes ELM seems to crush every other language/framework when it comes to bundle size. ELM bundles seems to casually weight about an order of magnitude less than other tech typical bundle sizes.
  • Relatively widespread: Compared to the other languages I considered, I think ELM is the most used to build frontends (it still remains a fringe comunity, though)
  • Relatively easy to learn Its ecosystem is very simple... there is often only one way of doing things, and its syntax is straightforward... that makes it easy to learn.
  • Coherent ecosystem The community around ELM seems helpful, not flawed by the dissentions I seem to have percieved in other communities, and its package system is rock solid (it enforces semver to published libraries, ensuring nothing will ever break)

πŸ’₯ CONS:

  • No SSR - That is not a small one... ELM cannot do SSR + Hydration. Meaning that we will have to choose between server side rendering and interactivity. I think I would have chosen ELM no question asked if it did suport SSR. But I'm not trying to build a SPA :(
  • Interop - As neat as the dev experience is using ELM, it is quite bad when it comes with interacting with JS. You have to communicate through ports, which are quite rigid and tedious. You'll also have much trouble on basic things when it comes to speaking non-elmish, like when deserializing JSON coming from an AJAX query (If i'm correct, you'll systematically have to implement explicit ad-hoc JSON decoders πŸ˜‘).

πŸ“š Framework:

Not relevant :) ELM is its own framework !

That said, elm-ui seems quite interesting as a library. I think I would use it

3️⃣ ReasonML/ReScript

It is an OCaml descendent.
It seems to put an accent on interoperability with JS, and pragmatism. But I don't know much about it except the basic syntax.

So any feedback is welcome.

βœ” PROS:

  • More familiar: While you could not guess what random code from the previous two languages is doing without any initiation to their syntax, Reason feels more familiar. It "looks like" something you would understand if you already know languages which are not considered as purely functional, but have some affinity with the functional style, such as Scala, Rust, Kotlin... and even JS.

πŸ’₯ CONS:

  • Messy ecosystem: Sooo... well... It takes at least half an hour to understand that Reason, ReasonML, ReScript, Bucklescript, and all that are actually kind of the same thing, I guess, but not really, but they're not anymore, but they are transitioning, but ... wait wat ? Couldnt someone tell me why all the fuss ? Couldnt we have one way to go ? And how am I sure I'm not starting to use a version that will lead me to a dead-end ?

πŸ“š Framework:

Like I said, I don't know enough about it, but reasonreact seems to be the way to go ! Any feedback appreciated

4️⃣ Haskell

The father of all languages. Over the decades, Haskell has never exploded in popuplarity, but it has inspired in one way or another most of the typed languages out there.

βœ” PROS:

  • Syntax & type system: Same as purescript... Haskell feels and is very powerful.
  • Performance: Not really something that is useful when chosing a language to write a blog, but Haskell can compare to C++ in terms of performance.

πŸ’₯ CONS:

  • Server only: There is no efficient way to use Haskell client-side. Weirdly enought, we'll face the same dilemma as with ELM (which is client-only).
  • Learning curve: Same as purescripts...
  • Somehow weird ecosystem: I wrote about it here, but Haskell has been out there for a very long time... meaning that you never know when a resource is relevant, abandoned, ...

πŸ“š Framework:

Given that Haskell is only running server-side, and given the "serverless" constraint, using Haskell with widespread frameworks to develop websites such as yesod seems out of the question. If using Haskell, I would have to write some kind of lambda which generates a fully static website. After a bit of research, it would seem that an aws lambda running aws-lambda-haskell-runtime should be a good match.

5️⃣ Clojure(Script)

Clojure (or Clojurescript if you want to compile to JS) is a Lisp language.

I included it here because I used to play a bit with Clojurescript a while ago, and I found it quite original, but I wont dive into details here, since I find it too diferent to be compared with the other 4:

  • Is is a fully dynamic language, no typing (there is spec, though)
  • Like all Lisps, it does not have a syntax, per se. It's only parenthesis πŸ€ͺ
  • Is is quite flexible

... but I have not investigated weather if SSR is easy, nor about its deployability on a FAAS platform (that said, it runs on the JVM, so it should be the same as Java), cold-start times, etc... and I'd prefer using a typed language. So I'd need a lot of convincing to go with that one ! (even if I like it to play, learn, and write prototypes)


πŸ‘‹ Conclusion

Okay, that was long. So I have questions:

  • What do you think ?
  • Would you have something to add or to correct ?
  • Would you be interested in following such a series ?
  • Which language interests you the most ?
  • Have I forgotten a FP language that you love and would like to be considered ?
  • Which kind of supporting tech (lambda, cloudflare workers, azure functions, github actions, ...) ?

If this interests some, I will post articles & thoughts as I develop this blog. Otherwise, well... I guess that will remain a private journey !

Thanks for reading, and stay tuned for the follow-up !

Latest comments (38)

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
 
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
 
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
 
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
 
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 • 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
 
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

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 ?

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
 
paras594 profile image
Paras πŸ§™β€β™‚οΈ

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

Some comments may only be visible to logged-in visitors. Sign in to view all comments.