Best utility libraries?

Hey y’all. I’m brand new to Rescript. I learned it last night after being incredibly frustrated with Typescript. I tried out ReasonML back a few years ago, and I liked it, but never got to use it in a real project, and eventually dropped it. However, I started my own company, so now I get to choose the stack, and Rescript is looking very good, especially since I can incrementally add it alongside the existing Typescript. (I’m using expo, and I was pleasantly surprised how easy it was to integrate so far)

I remember one of my pain points when I tried Reason was that the stdlib was kind of limited at the time. The Rescript stdlib is much better it seems, and has ALMOST everything I need.

However (and this brings me to the question), I’m a big Ramda user, and I’m missing some of the functions that are in that library. I was wondering if the community has settled around a more extensive library for FP.

As an example, I had to implement my own intersperse function while I was playing around, because I didn’t see anything that looked like it in the stdlib. Also, I rather like reject (opposite of filter) because I’m often filtering out things, and it makes the code read nicer. path was another nice one, which would go down an object by a list of keys. I actually rarely used it, because it would throw exceptions if it couldn’t find what it was looking for, but the Rescript version could just return option.

I saw Relude, but looks like it’s more geared towards Reason and Melange, and based on the conversations I saw on their github, looks like Rescript isn’t a priority. Funny enough, I actually made a library like this back in the early days of Reason, and I could port it over, but it looks like Belt takes care of a lot of it. It also made heavy use of infix operators, and it seems like Rescript is moving away from those (much to my dismay, haha). Then again, if no one has tackled this, I could copy it, take out the things that are redundant with Belt, and remove the infix operators. This was the repo: https://github.com/jonlaing/rationale

TL;DR Are there good extensions to the stdlib like a Ramda equivalent?

2 Likes

There is tablecloth, I’m in process of converting it to rescript (more or less done).

It does have intersperse function.

Since it’s not fully production ready, it has to be installed like this:

yarn add https://github.com/darklang/tablecloth.git#next

Hope you’ll find it useful.

2 Likes

As an off-topic, I’m a bit curious about your frustration here (we’re about to use TS in a bigger project ourselves). Not to start a flame thread, obviously. :innocent:

1 Like

@jonlaing I’m actually working on a binding for ramda which I’m using in project.
Hopefully, it will be finish soon :wink:

@ollehar

I don’t intend on being too hard on Typescript. It’s a big improvement over vanilla JS. I should also note that my favorite language is Haskell, but I never get to use it in production, so that informs a lot of my thinking. I’m heavy into FP, which Typescript will do, but it’s not really made for it.

My problems came from having to hold the compiler’s hand a little too much. It has type inference, but it’s not all that sophisticated. Eventually I was writing really complex types just to make the compiler happy. Also the way it handles interface inheritance frustrates me. Oh, and the no-implicit-any rule (which you can turn off) drives me nuts. It makes writing little lamdas (closures) overly verbose and ugly. I’m getting to the point where I’m turning off warnings and casting things constantly just to make the compiler shut up, and that kind of defeats the purpose of a typesystem. (I’m validating my casting through unit tests, so I know I’m right, but the compiler isn’t smart enough on its own.)

I think it comes down to the way it was built. It was meant to be a layer on top of JS. Adding a typesystem to a dynamically typed language is a tall order, and given that criteria, Typescript is very good. But as a design philosophy, I think it borrows a little too much from OO, both syntactically and in the way it deals with inheritance. Overall it did improve my productivity over JS by catching a whole class of bugs before I even ran the code, so for that I’m grateful. But I guess my project grew to the point where I need more robust generics than Typescript can offer. You should see some of the monster types I’ve had to write to do something that would be a one-liner in Rescript (I think, I haven’t played with it too much yet).

There’s also a question of developer productivity/happiness. I have to write so many type annotations because Typescript isn’t smart enough to infer for sufficiently abstract and generic code. Really, I’d love something like Haskell’s typeclass to work with, and you’d think Typescript’s interfaces would be a good fit, but I’ve really struggled to make them work the same way. After a certain level of abstraction, Typescript falls apart in my experience.

So, overall Typescript is a great tool, but maybe not the right tool for me and my project. I would 100% choose Typescript over vanilla JS, but I’ve been on the lookout for good alternatives. I’m excited to get more into Rescript because its typesystem is way more robust, and I had good experiences with Reason in getting the level of abstraction I’m interested in. I looked into Haskell-like languages that transpile to JS, but they don’t quite have the support I needed. Most of what I do is in React Native, and a lot of those languages don’t play nice in that environment. I’ve already got Rescript integrated into my RN project with zero hassle, so I’m pretty optimistic about it.

2 Likes

That looks a lot like what I was looking for. Thanks! Now I’m on the lookout for something with ADT’s because I’m a huge nerd, haha.

Speaking of which, is there any talk of allowing the ++ operator to work on things other than strings? Should theoretically work on any Monoid right? It would be nice to do [1,2,3] ++ [4,5,6] instead of Array.concat([1,2,3], [4,5,6]). I mistakenly assumed that would work when I was trying out Rescript for the first time. Just a thought!

That’s great! My only real gripe about Ramda is that it returns undefined for a lot of its functions. If I could have a Ramda that returns option<'a> I’d be very happy. Also Ramda and Typescript don’t play well together, which is where half of my problems with Typescript are coming from.

There’s only a set of operators you can redefine, and there are a lot of discussions about infix operators here that you can read through. But they aren’t really recommended:

let \"+" = Js.Array2.concat
let x = [1] + [2]
let y = 1 + 2 // dont work anymore

Playground link

After using rescript for almost one year,i found that i would use vanilla js rather than ts. The unsound type system makes ts too complex to write your code if not using type any.

2 Likes

I totally understand the frustration. I definitely start to feel that if the type system is so haphazard, there’s hardly a point to having one at all. I could see starting to feel that way after a year of using a real type system. Having some level of static analysis beyond linting is a nice sanity check for me right now since I’m the only developer and can’t have code reviews at the moment. I preferred vanilla JS to TS when I was working at a bigger company, and had a dev team and a full suite of unit tests and a QA team. When coding from scratch by myself and trying to be quick about it, just having the editor give me a little red squiggle was nice for a while. But now that I’m nearly at the finish line, and I’m pretty confident things are working properly, it’s starting to feel like a hindrance.

Really looking forward to integrating Rescript into the project more. I have to build out a web front end next and I’m probably just going to use Rescript from the jump.

Hmm, yeah I don’t know how ++ is implemented in the compiler, but I might jump into those conversations to advocate for it being available for at least arrays in addition to strings. I’m wondering how strings are represented in the compiler. In haskell they’re lists of characters, so it would make sense that the same concatenation operator would work for both arrays and strings.