These are chat archives for ramda/ramda
That happens because Ramda's
apis compatible with FantasyLand 1.0, whereas Fluture follows 3.0.
The argument order of
apwas flipped in FL 2.0
Actually, @Avaq, the
ap change was part of the 1.0.0 release. Ramda is currently compatible with
@rickmed I've used typescript extensively with ramda and my conclusion is, it doesn't work well for functional programming, its built for a different style of programming, it can't detect types of first class functions. There's no higher kinds. Doing standard ramda compositions in typescript is painful. There's no notion of currying, so if you want accurate definitions, prepare to write a lot of overloads...
Common FP typing idioms really slows down builds, things like union types add up compile times (With TS my initial compile was 165s without its 5s). It might be ok on smaller projects, but it was just untenable for us.
I also found the bugs we get aren't the ones typescript could catch. Maybe things will improve, but I think its best not to stick with JS, or use a different language entirely. And I'm not sure how much it can improve, I think typescript's model is almost diametrically opposed to FP. Writing FP code with
--noImplicitAny makes composition pretty ugly, coding without it means your opening up the flood gates for all kinds of type errors. Non nullable types are great, but there's escape hatches like
!. accessors, and so its sort of self defeating.
And I'm sad saying this, I was really excited about TS 2.0, non nullable types, more literals for unions, discriminated switches, its all sounded great. But if I could go back in time and tell myself not to adopt it, I would.
I get a lot of value out of sanctuary, and I find myself leaning on it more and more. I'm tempted to experiment with sweetjs to make the whole sanctuary experience a lot less verbose.
I have no experience with flow types, but I assume its much the same.
Also worth noting you can get a lot of value out of the typescript ecosystem without actually using typescript. VSCode for example automatically acquires type definition files for npm modules, so if you
require('ramda') you get code completion and inline documentation without doing any setup at all. The same is true for your project's module.exports or es6 exports. The typescript language service can be of use to you in a vanilla JS project. I'm sure the above is possible in any editor as well.
@gabejohnson thanks for the advice! :D I'll give that a go
@rickmed my pleasure
I think the features Typescript has are designed to make imperative code a lot less dangerous. Most of the bugs Typescript would catch are the sort of bugs you already don't have if your writing in a functional style. The way we write code seems to already prevent the bugs Typescript would catch.
1 example would be handling possible undefined values. Possibly undefined values are common in JS because a lot of api's have optional parameters, or variadic signatures that are all considered valid. But if you keep different functionality in different functions, and you ensure your data structures are consistent, and you use functions like
R.propOr - there aren't any possibly undefined values left.
Another example union types can be used to notify you when your not covering all possible branches in a given domain. And this works really well in ML influenced languages. But TS' union types are both slow to compile and awkward to use. I assume their slow because most people using TS aren't using unions often enough for optimization to become a priority. They're awkward because if your not just using string literals you need to rely on a shared key on each possible subtype in order to discriminate, which can limit its usage and prevents it from being a general pattern you can employ again and again. So when we did have a bug for not handling every possible case, it was impossible, or impractical to use typescripts discriminated unions to do so. It also encourages you to use switch statements (in order to discriminate unions), and despite eslint making switches less dangerous, I still avoid them.
I find if your writing code point free almost exclusively, and keeping each function's type signature as simple as possible, its actually quite challenging to end up in the problematic situations that would warrant typescript's poor performance, verbosity and awkward syntax/requirements.
SO I think types are great, but typescript itself, from my experience has limited returns if your writing functional code. And even worse I find typescript inhibits writing FP code, because you need to give it type hints so often that you give up and write code manually/imperatively so it can implicitly detect the correct type without the noise of annotations.
If you want typed code, I'd recommend checking out purescript, or F# (via fable), or Elm.
I should also state, I'm not at all saying typescript isn't a great project, it is. It's just got a particular target audience, and its made concessions to maximise the benefits for that target audience. I think the target audience is OO with nested conditionals, variadic apis, optional arguments and inheritance. If your writing code that way, typescript is a powerful/useful tool.
Its really helpful for me to keep a record of what bugs you encounter at work, categorise them and then think of programming practices that could prevent or decrease the chances of that bug occurring. Sort of like Crockford's good part's.
E.g. I found coworkers were using template literal syntax, but with the wrong quotation mark when calling rest endpoints. It was infrequent but it came up often enough that we created static functions to call each endpoint, and removed all manual string construction from the app. Now that bug can't happen.
Another example would be in virtual dom, having a trailing comma, or accidentally creating a sparse array. We adopted comma first style to make it painfully obvious when a comma was missing or when there was 1 too many commas. This also prevented a lot of merge conflicts when different branches were iterating on the same view.
So they are the kind of bugs we were getting, and typescript could not help with those bugs. But TS is still a valuable project in other contexts I think.
const getLeaf = ( startID, node) => node.leaf.reduce((accum,child)=> node.id==startID? [...accum, child.id, ...getLeaf(child.id, child)] : [...accum, ...getLeaf(startID, child)] , )
R.tapwas introduced, and any hints regarding the name? would really like to know
Thank you @rickmed. And I never tried ts-static-land btw, looks impressive! Gotchas are hard to write about I think because they're always context dependent and nuanced, but maybe in the limited context of FP in JS it could be ok?
@kedashoe thanks for adding that to your PR! That particular issue stumped for at least an hour yesterday :). And good luck with your tech stack choices at your work.
@kwijibo Thank you
Should note, I think the TS team is interested in FP, and they're looking into HKT (there are some issues bouncing around on their github) but I think there's just less demand for it than other things, and its so late in the game it may always feel awkward to write FP in TS.
static-landhas been a very exciting combination lately.
kefir, turning events and promises into streams and acting upon those.
partial.lenseshas been a godsend, solved so many problems with handling arbitrary JSON data (and, well, data in general)
It's difficult to give a recommendation without knowing what sort of data you're dealing with, how often will it need to be accessed etc
@rickmed its all on issue/pull request threads on a private repo :(
From here on in I'll keep the notes in a gist and try to turn it into a blog post though.
Either, more or less :(
Maybealready is a huge help for taking in data for transformation and chaining the transformation steps through
partial.lenseshas been a lifesaver lately, esp. since it works together with ramda so well