Personally I prefer questions of the kind: what’s the best solution for problem X.
Rather than: what language is best for programming style Y.
In general, questions of the kind: is pure FP good or bad seem difficult to answer abstractly.
It’s a bit like asking: are flat headed screwdrivers better, or star headed ones better? I guess it depends, on what screws you need to operate on.
I guess the inner child in me might see a yellow tool and a pink tool, and enjoy the pink one more, because it’s a nice color. Then start playing only with the pieces where the pink tool applies.
One day, the inner child would grow a bit, wants to build something they thought about, and learn that a combination of different tools are needed.
Okay I got it, you don’t like the question, so you ignored the parts you could have answered, and instead began talking about colors. I didn’t know you had the same rules and attitude like stack overflow mods, where their ruleset prevents you from asking questions in a way that encourages people to include their personality combined with experience in their answers. Thought I could ask a honest question and that the friendlyness towards new people in this community would allow it, without attempt to teach me about my wrongdoings.
Asking for more experienced people’s opinion obviously does not resonate very well with some people, however why should we not be able to ask what we really are curious to learn. I would have asked the same question if we were face to face without thinking about your preference and if i worded it to your pleasing.
I’m sorry i asked this question. Thought this community could handle it.
Hopefully this will not turn into a discussion and steal all the focus.
My 2 cents. rescript is an ocaml frontend. ocaml has decades of FP excellence applied to it. I’m a daily TS user, and I like fp-ts. However, rescript & ocaml are where the gold is at.
Does rescript lack features to make it a good pick for fp?
Not common features, no. I wish typed algebraic effects were in the compiler, but I can’t have it all.
you don’t like the question … Thought … could handle it.
I think there’s a mis-comm here. no one is dunkin’ on you, brotha. I read the replies above as kind & genuine feedback to your question. It’s a challenging & abstract question to answer, they gave it a jab.
Hey man,
I think you and I might have a similar sort of outlook. I like the purity of FP. Where we might differ though; in the end, I need to get shit done.
Why did I even switch away from TS? Well, first I actually went back to JS - believe it or not. I realized that TS doesn’t really do anything for me. It’s just JS with type annotations, they don’t help me much. I needed something more FP-ish. Hello, ReScript.
I like it because it’s strict, but it doesn’t try to turn practical problems into mathematical abstractions. I.e., it’s pragmatic. I think it should be even more pragmatic. See this: When helpful becomes hurtful - some areas where ReScript is problematic - #5 by philiparvidsson
Notice how I speak about “warts.” ReScript is full of them and will likely gather more. Why? Because it’s pragmatic. You bend the rules to fit the need. That might not play well with your mindset - it seems you’re looking for something pure. If that’s your cup of tea - then I think you should maybe try PureScript (I never heard of FP-TS before). I like the idea of it, but in practice, simple things become too complex for me to get stuff done in a feasible amount of time. Maybe I’m not smart enough for pure FP, I don’t know.
I don’t know about FP-TS, so let me compare to PureScript:
You would have to give up beautiful code. Good lord ReScript is ugly and full of warts. In the stdlib and JS stdlib (Belt.Array, Js.Array, Js.Array2, object, object_, exec_ and all sorts of weird names - likely these will be cleaned up at some point). And promises (then, thenResolve, all, all2, etc). But there are benefits to this as well: It makes you read code carefully (this is more compared to JS/TS).
As for lacking features - no, absolutely not. You will have them in ReScript too, but they will not be anywhere as beautiful to look at. The pink tools analogy is actually not that bad, but maybe I would put it this way: Imagine two plumbers. One of them has clean, white clothes and a toolbox with polished, shiny tools. He’s very careful doing your plumbing work, doing things neatly and not getting anything dirty. His name is probably Gifuncio and he’s probably a handsome italian or something.
Then there is Mr. Replumbo. His clothes are dirty, his tools are dirty, but he’s also an expert. He gets stuff done for you without hesitation, but his tools are not shiny.
Doing a commercial or some theoretical setup, Gifuncio is probably my pick. For any real-world plumbing projects, I’ll be calling Mr. Replumbo.
Does that sort of make you understand how I view the difference?
Are you programming for a living and need to get stuff done, or do you do write papers for research or experimental hobby projects? Do you program to solve practical problems or to write beautiful code? These are not mock questions - both sides are fine, I’m just trying to help you think about this.
If you want to write beautiful code, I would never, ever pick ReScript. I could even argue regular JS probably can look better. But ReScript helps me get stuff done.
The only runtime errors I’ve had so far are due to me writing bad bindings/externals. In the future, when we have ready-made and well-tested bindings, things will be different. I think ReScript is on to something, but I can also see why it’s off-putting for some.
I recently read a post about comparing OCaml (ReScript inherits the similar mindset, IMO) and Haskell: https://github.com/sidkshatriya/me/blob/master/005-On-the-lack-of-integrated-tooling-OCaml.md
It also mentions ReasonML as well, and I believe this can answer some of the questions you have.
Also as a newcomer to the ReScript community, I found this (rather small) community very welcoming and kind, so… I really hope you don’t get offended
Thanks for the great answers so far (and funny analogy about the plumber haha)! Exactly what I was hoping for. I feel I already got my questions answered, but please feel free to chime in, if others have anything to add.
In my experience neither are great for fully functional programming for similar reasons: the language doesn’t align with the goals of pure FP. This is in stark contrast to a language like Scala or of course purescript.
My advice would be to be pragmatic in your functional programming and you’ll go very far with ReScript.
I would have to disagree based on my experience. ReScript is much more of an FP language than Scala. Functional programming is not defined by ‘the goals of pure FP’ (that would be a circular definition anyway). FP is enabled by a few core languages features, which both ReScript and Scala have, but Scala’s emphasis on mixing OO and FP detract from it.
E.g. here’s a perfectly valid Scala expression: val x = if something then "yes" else 0
, and its type according to Scala is Any
. This kind of thing can (and has) led to real-world production code bugs. Thankfully ReScript stops this craziness at compile time.
I’m a full time typescript react developer, and like a lot of other frontend developers I have gained an interest in functional programming over the last several years. I have played with and explored into almost every functional npm library you can think of, including fp-ts, and I’m always looking for ways to improve my code quality.
What I’ve kinda learned for myself over the years, is “pure” functional programming is great in theory but in practice has some tough issues. I’ve inherited some projects that were done by FP “purists” (although in JS), and conceptualizing and understanding how everything tied together was a side quest in it’s own. I had hundreds of different functions I can workout what each does on a micro level, but understanding the flow of everything you had to step through so many different calls and keep a mental note of where you’re at as you’re several levels deep into the stack. Like, you can easily see “what” the function does but not “why” or “where”
Now this could just be the fault of those developers, or this could just from my lack of knowledge of certain patterns, but my opinion stands that there is a nice middle ground between purity and practicality. To me, the main things I’m looking for in an FP based language like rescript is (A) immutability, (B) sum types for domain modeling, (C) pattern matching, and (D) easiness of inline expressions. I think rescript does a great job in supporting all of the above, where I’m able to write “mostly pure” code but maintain a pragmatic approach in my entry function / bounds modules.
I feel as though fp-ts tries to push some of the more abstract algebraic patterns into a language that doesn’t have native support for it, and you end up with unnecessarily complex abstractions for simple problems. The few times that I’ve tried it out I’ve always ended up with a difficult to maintain codebase. And once you start using it you’re basically tied into the entire ecosystem. My codebase was bug free for sure, but was so hard to extend or update it at all; and issue I haven’t had with my time in rescript
fp-ts is hard to fully grasp, when you look at the documentation, if you’re new to functional programming. But is all of it even relevant, or is this a comparison where less is actually more?
Agreed. It is not very user friendly. It is trying to emulate Haskell in TypeScript without much explanation. It is very much not user friendly to FP and category theory noobs.
I’d be curious to know how much you’d have to give up from fp-ts if you switched to rescript instead. What would the pros/cons be from someone who has more experience with FP?
That is a tough question because one is a language, and one is a library. I guess you lose all the monad like structures like IO and Task. You also lose the do comprehension. However, I would argue that both were cumbersome in TypeScript.
I read from the authors that they were not aiming to target the language for writing functional clean/pure code, but that they had a more pragmatic approach to coding - that eventually it turned me off.
This actually is way more historical than ReScript . Ocaml/F# have been functional first programming languages, which means they have first class support for FP principles, but allow some imperative stuff if you want it.
If you are wanting a more pure FP experience, you need to look towards PureScript. Really great language, but the learning curve is much higher and the learning materials are not quite there.
If you want to see the power of ReScript, go look at Scott Wlaschin talks on YouTube. He uses F# for his examples, but everything he shows can be done in ReScript.
I should have mentioned monads by name, because that’s what I was referring to.
I love all of the languages I mentioned but ReScript is by far the best when you’re happy to be pragmatic about where side effects occur.
That is a tough question because one is a language, and one is a library. I guess you lose all the monad like structures like IO and Task. You also lose the do comprehension. However, I would argue that both were cumbersome in TypeScript.
I’m curious what you don’t like about “Task”. Although I’m very new to fp-ts and ReScript I do think that Task together with chain, map, fold operators is much more readable than “then” and I was also surprised to see async await being requested for ReScript as I very much prefer pushing errors to the forefront like this fp-ts overview: Error handling, the functional way (part 1) | Troika Tech
If you are wanting a more pure FP experience, you need to look towards PureScript 1. Really great language, but the learning curve is much higher and the learning materials are not quite there.
PureScript is on my radar, however most resources I could find was introductions for Hashell developers, whereas I’d probably need one for JS developers or even for dummies
If you want to see the power of ReScript, go look at Scott Wlaschin talks on YouTube. He uses F# for his examples, but everything he shows can be done in ReScript.
Thanks I will go watch them on youtube now.
I guess my ideal language would be functional first but allow imperative code - yet discourage it and default to functional style. I’m not sure if you’re implying that ReScript is functional first? Or if it changed and got more pragmatic as it changed name from BuckleScript to ReScript?
That was also my first impression when considered giving Scala.js a try. Didn’t like all the object-orientation, as I expected a more functional oriented language.
If you commit 100% to leverage fp-ts to its fullest (ie. replacing native js datatypes such as string, array etc. with fp-ts ones), I can understand and agree with you.
But somewhere in the docs I do remember reading that they recommend that you don’t make your functions based on the flow/composition in fp-ts, but just stick to normal fp best practices like you’d typically do and it should be fine. So if it’s mostly Task, Either, Option, pipe, flow and of course quite a few others, I don’t think it should necessarily be too difficult to migrate from fp-ts to something else or even just vanilla. Depending on what you compare with and the codebase of course.
But if all you’re doing is using the simplest monads, then there are multiple packages out there that provide an Option and a Result/Either type with a fluent api that I’d argue is much more readable and pleasant to work with than a heavy pipe overload (purify-ts, prelude-ts, boxed, ts-option). I would consider fp-ts to be overkill here. Rescript has a native Option/Result type and piping is built into the language
To put it another way, you actually don’t need to dive deep into a Functional Programming rabbit hole to be productive, ship good quality code, and avoid most bugs. You just need to follow some basic best practices like avoiding global state and unbounded use of side effects.
But on the other hand, you do need a solid type system that actually isn’t full of hidden pitfalls. If you don’t have that, then no amount of Functional Programming can help. This is what ReScript gives you that TypeScript doesn’t.
As Yawar mentioned, types are pretty powerful. I suggest watching as much of Scott Wlaschin talks to get a good feel on how to use them. F# syntax is a bit different to ReScript, but not by much.
For example:
F#
type Apple = AppleVariety of string
ReScript
type apple = AppleVariety(string)
I’m not sure if you’re implying that ReScript is functional first?
Sorry, ReScript is a descendant of Reason/OCaml, so it is functional first.
I’m curious what you don’t like about “Task”. Although I’m very new to fp-ts and ReScript I do think that Task together with chain, map, fold operators is much more readable than “then” and I was also surprised to see async await being requested for ReScript as I very much prefer pushing errors to the forefront like this fp-ts overview: Error handling, the functional way (part 1) | Troika Tech
It’s not that I don’t like it. I am just saying you lose it. However, you can easily write your own Task in ReScript. ReScript provides a type system where you can build this or use Result and Option which are the kind of building blocks you need for handling almost all situations. Or you can just use or build off the many Promise implementations.
I want to kinda show you how that example article would look in rescript so imagine this implementation
Our final code would look kinda like
I did this off the top of my head, and with no implementation, it may or may not be 100% correct, but it should be close.