DEV Community

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

Learn functional programing with me - Part 1 : Language choice

oguimbal profile image Olivier Guimbal ・9 min read

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 !

Discussion (40)

pic
Editor guide
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 Author • 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 Author • 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 Author • 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 Author

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 Author

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 Author

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 Author

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

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

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
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 Author • 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
zacharysarette profile image
Zach Sarette

Why not Scala?

Collapse
oguimbal profile image
Olivier Guimbal Author • 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 Sarette

Fair! :)

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

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

Collapse
michaelgrigoryan25 profile image
Michael Grigoryan

Try toying around with Racket too πŸ€ͺ

Collapse
oguimbal profile image
Olivier Guimbal Author

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
michaelgrigoryan25 profile image
Michael Grigoryan

Yeah you can't use it in front end. It's a backend language. Personally I haven't ever tried clojure

Collapse
jesuisnima 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
charles_orileyjr_b5587 profile image
Charles O'Riley Jr.

I would be interested in reading more information on Haskell, PureScript, and Yesod

Collapse
oguimbal profile image
Olivier Guimbal Author

I may choose Haskell or Purescript (a small spoiler: I may choose several languages, and do the same thing in parallel with those, in order to compare them) ... so stay tuned !

But if you want to know about Haskell (or Purescript... they're almost identical), the typical learning resource is learn you a haskell ... it's not very practical, but works to get the idea.