1,295 karma · joined March 19, 2013
Elm has been personally an inspiration too. Nice set of decisions and tradeoffs for what they're trying to achieve, though yeah, mainstream syntax might not be one of them, but that's fine.
Btw the ReasonML you're talking about is still just a syntax transform; you're really asking whether OCaml/BuckleScript has these implementations. There's no generators; but I do believe they can be built on top of algebraic effects.
Regarding jargons: you don't have to worry about that =). Though I think what's more crucial is the way the jargons are conveyed, rather than the meanings themselves. I work in the ReactJS community, and there's basically as many jargons (some of which I myself don't quite understand...) as in FP, yet people seem fine with them. We're still not gonna go "monad this monad that" like you feared. Though if the JS community starts picking up terms like monads in the future thanks to Reason, then all the better.
In that regard, "jumping on the types bandwagon like it's some new discovery" is exactly right, because it's indeed lots of people's first language. But I don't see why this should sound so negative. Newcomers are now introduced to types and they're amazed by them. That's welcomed and we shouldn't feel they're taking away our own shiny toy and tainting them or whatever.
I think it pays to be nice to beginners. Sure, you don't get the usual quality you're looking for in a niche expert language where communications are atomic, on-point, and lossless, but that's _OK_. All in all, things like a better type system, better language semantics and better paradigms are still worth fighting for.
Algebraic data types are a basic feature.
* Yeah! I know I'm pure-hearted at least
* JavaScript will be around for a long time. Our stance is more gradual improvement than world-breaking changes all over the place. I'm still trying to phrase this correctly, because sometimes when Reason gets mentioned, the immediate reaction is "wow they're gonna rewrite everything again, kids...". Our interop story is pretty damn good. Please check it out!
* See ReasonReact's license =)
* The more successful Reason is, the less we'll drink. Kidding
Our discord channel is at discord.gg/reasonml. I think we're a bunch of pragmatic and nice folks. It'll take time for people to understand our stance, but blog posts like these really help showing what we're doing.
The alternative, and maybe a better way to do this, is a FUSE-like system, like Expandrive. Lazily fetches files from remote.
Give it a try! Ping us if you need to: https://github.com/facebook/reason#community
Which imo is a bigger achievement! Being able to gradually convert a js codebase over is one of our main goals.
For example, I depend on Foo v1, and would like to upgrade to Foo v2. Currently mainstream languages either use a type system to indicate the upgrade was unsuccessful (can't catch everything, and still require the user to patch things), or allow the user to muddle along, knowing things might break subtly but not enough to be "bothersome" (e.g. node ecosystem).
So one Foo upgrade is costing O(n) in refactoring cost where n = dependents of Foo. Given enough patience the Foo author could make an adaptor between v1 and v2 to reduce it to O(1) upgrade (inside Foo itself), but this is asking so much that nobody sensibly do it, except for big projects which provide great migration warnings, codemods, bridges, etc.
This, combined with, say, plaintext structural sharing/diffing between library versions (so that code size doesn't blow up if you have 5 transitive dependencies on Foo), might solve two important problems of dependency/versioning hell imo, and keep software as fresh as realistically possible.
I understand the general version of this is uncomputable, but that's my question: is there research on constraining the expressivity of an language just enough to make version upgrade of a library mostly automatable? Here's an idea: first-class support for fetching the code of a transition between v1 and v2, half-automated by the language & tools, half community-maintained & uploaded to a dedicated place. Alternatively, push as much as possible to data instead of functions, to make writing transition code (which would simply be massaging data from one form to another) much easier, like GraphQL deprecation strategies (https://facebook.github.io/graphql/#sec-Object-Field-depreca...)
Real-life example: two React.js components written under two different React versions naturally don't interoperate. You can't include one inside another. Right now you "can", but this is thanks to sheer human effort from React.js to maintain backward compatibility, so components using React 15 work with components using 14, etc. Same for Java, Windows, and others. The language doesn't help you with that at all. Semi/fully automated version transition/code generation would be a killer language feature.
Because of the clean mapping from one syntax to another, you can toggle between the two fairly easily: https://github.com/facebook/reason/wiki/Newcomer-Tips-&-Tric...
Currently it's a syntax on top of OCaml. But we'd like to polish the OCaml ecosystem tooling too; we're calling the umbrella project "Reason".
BuckleScript's author (hongbo_zhang here) has been incredibly responsive and welcoming.
We'll be publishing the React.js binding on HN in a few days. Stay tuned! We (including Hongbo) are all sitting in irc #reasonml and https://gitter.im/facebook/reason
Having worked with Reason, JavaScript, and the bridge between the two, most of my errors seem to fall on the JavaScript side. So I guess the type system's indeed working =).
readThisFile: string -> (string -> void) -> void
Usage: readThisFile('foo.txt', result => ...)
You have a double void here. Which is the hand-wavy justification as to why callbacks don't compose. On the other hand, a promise's value is Promise<actualTypeOfValue>, which you can pass around as data without asking the other end what it wants to do with the value (aka decoupling). You do have the imperative action at the top to kick the whole chain into motion, but the intermediate stuff are most of the time side-effect-free.Hopefully that was clear enough to see that passing actions around is akin to controlling the flow with e.g. if-else, and that passing data around is declaring how your tubes/rail tracks/whatever analogy for monads are constructed, aka data flow.