Hi, I’ve been learning purescript (and FP) with a personal project for some time. I love the expressiveness of the language and the well thought out standard libraries. My intuitive test for how good things are is, do I understand how the libraries fit together and can I generally remember where to look for a function? After some careful study, I almost always seem to get it. I’ve really enjoyed my experience.
Writing these types is helpful in that I truly understand the library in question when I’m done. If this happened infrequently it wouldn’t be a big deal, but I’ve been experimenting with various libraries and major versions of libraries and it’s turning into a significant portion of the work. Initially I convinced myself that if I were more experienced with purescript it wouldn’t be, but I’m beginning to wonder if that’s true. A good portion of application development is turning into library integration and without a large community to amortize this work over, the problem may persist even if I were better.
Do you have an opinion on the magnitude of this problem?
Is there any work planned to make this easier? (E.g. code generator based on typescript types?)
Are there any good tutorials out there or codebases to study that handle this problem well?
Are there other languages that others have considered that make this easier? (E.g. I don’t BuckleScript/ReasonML nearly as much as purescript, but I’ve read that all the “bs” type annotations make wrapping easier. My impression could be wrong. I’d really hate to give up on types, but a dynamic language like ClojureScript makes interop easier at the expense of having to write verbose clojure specs. I realize there is severe selection bias in asking this question of this community, but where else would you ask?)
Any thoughts are appreciated. Thanks!!
this being a huge problem, inheritance, etc). It requires care and often intimate knowledge of what a given library is doing (is it doing sneaky reference checks and adding expandos?). Getting something wrong with a TypeScript type isn’t a big deal since no one expects soundness, but getting it wrong in PureScript can lead to some very unintuitive results, especially with regards to purity and value semantics. Other languages like BuckleScript or ClojureScript don’t expect purity or value semantics, so are therefore more forgiving. By forgiving I mean one cannot make as many assumptions about code since effects can and will happen anywhere.
In my experience, attempts to directly type non-trivial foreign libraries leads to results that are both a chore to maintain and use. When bindings are necessary, my advice is to write minimal and opinionated bindings according to your use case (and PureScript semantics) so you can spend more time writing real code. Otherwise, I would just go ahead and maybe write that component in TypeScript.
i think you have to look carefully at the returns on the efforts taken to wrap JS…sometimes it’s better just to use Purescript in the parts of the program where you really get a lot of benefits from the expressiveness, readability and “making invalid state non-representable” aspects - that can be a pretty big win, depending on the application.
Having sweated thru writing types for (the old row-based) effectful call backs for D3 i think now that it bought me nothing, and i certainly didn’t feel that i’d lost anything when we went to plain Effect on them.
What we’re doing now is to enforce a really strict translation layer (just Purescript types to Purescript-but-really-JS-records) before the FFI. That and some informal rules about trying to keep the computation wherever possible on the PS side of the FFI.
I remain convinced that there is a way of expressing what D3 does as an eDSL that i would like better than D3’s-polymorphic-in-all-the-wrong-ways API but i haven’t done any work on it recently.
Absolutely agree with that last paragraph. That’s dead on, IMO
afc, the translation that you describe, PS records to JS “records” is what I’m going for also. Thanks.