Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
25 Days of ReasonML (medium.com/lilactown)
121 points by based2 on Feb 4, 2018 | hide | past | favorite | 40 comments


I've been learning ReasonML for React Native these past few weeks. I love the static typing. I can work on my editor for minutes at a time, and when things compile I see it "just work" on my phone. This is important since reloading a native app is not nearly as fast as reloading a web page.

The best part is how FAST the compiler is! It blows me away how fast the reason/ocaml compiler is, considering it spits out JavaScript AND type checks at the same time. Babel, TypeScript, Flow, etc. are all slow as dogs by comparison :)


How are you handling navigation?


I haven't gotten that far yet, but I'm planning to use their minimal built-in one: https://reasonml.github.io/reason-react/docs/en/router.html


ReasonReact currently only handle browser routing (it hooks directly into window.location API. So for ReactNative, it could do it the way you used to do with Javascript.


Do you use any third party libs?


I find ReasonML a VERY HARD sell when F# is sitting there waiting. If I could get people onboard with an ML, why wouldn't I use F# with it's massive backing ecosystem and fantastic server side runtime(node has come a long way, but it's no CLR)?


ReasonML is pushing hard on the "it's a better JavaScript" angle, which has a lot to do with it's popularity at the moment. In that regard I think it will be an easier sell than F# as ReasonML grows in maturity.

Part of the problem with adopting an ML is that it feels like a huge departure from mainstream software development. From the syntax, to the build tools, to the concepts one uses on a day-to-day basis, it can be hard to slog through to get to the point of feeling productive.

ReasonML is focusing on four things to help alleviate this friction from adoption:

1. Providing a more familiar syntax

2. Providing simple, high quality tooling built on top of a familiar ecosystem

3. Providing high quality documentation that focuses on onboarding developers who are coming from these other ecosystems

4. Providing a "killer-app" that can show the power of the language and draw peoples interest - in this case, Reason's integration with React through it's ReasonReact library and support for JSX.

I think that these 4 things really make a difference when getting "people onboard with an ML," which is why the ReasonML community is something that I'm betting on for the mid- to long-term future.


I tried getting into F# and for someone not running on Windows without knowledge of the CLR and .NET ecosystem its a hard sell.


Was this recently? Things change really fast, within the last year or so we got ionide and core clr support. I've read of people preferring the experience of F# in VSCode these days.

Just a few weeks ago I got an F# project with TensorFlowSharp up and running on OSX in VSCode with the ionide extension. It JustWorked™.

In any case, I'd suggest you give it a crack again if you are interested. The experience has improved greatly and the tooling seems pretty great now on Linux/OSX. I've been following it for 3-4 years though, so I certainly understand how it would seem like a non-starter in the recent past.


I found getting F# dev environment set up on Ubuntu was super easy. That said that I found Merlin in Vim to be better than Jetbrains Rider. With Ocaml/Reason you should be able deploy via native binary. The build times and deployment story are going to be similar to Golang on the backend - if it works. With F# you have to deploy the CLR too.


I don't have enough experience with ReasonML but the primary reason I am hesitant to adopt F# in my production applications (which currently use typescript) is because of following reasons:

1. Record types are very inflexible. It is, for example, not trivial to do things like get a new record type by adding a few fields to an existing record types.

2. F# supports only explicit interfaces. Making records implement interfaces requires defining getters and setters for every property. And requires explicit casting when you are sending a record to a function that uses an interface.

When you don't control the types (as is often when working with third party libraries) this becomes a major annoyance especially when you are habituated to typescript's structural typing.

While I would like to see opaque types in typescript for some use cases, I really think having structural types, implicit interfaces and erased unions by default makes life a lot easier, especially when it comes to interop with wider js ecosystem.

At the end of the day it quickly becomes very obvious that where as typescript was built from ground up to embrace javascript ecosystem, F# was not. As a result, when targeting javascript, a lot of design decisions which were based on limitations of CLR being a C# focused object oriented platform come across as bizarre and jarring. For instance why do we need both modules and namespaces ? Why are statically resolved type parameters only supported in inline functions ?

I will admit that this can be very much a case of me being more familiar with typescript and not so much with F#.

I do have a deep appreciation for both F# and Fable teams who have been incredibly helpful in stackoverflow and gitter. I strongly prefer F#'s syntax despite being a full time JS/TS developer and F#'s type inference is far better than what typescript offers today and at times it feels almost magical.

I also think that Fable's approach for generating babel compliant AST and taking advantage of babel ecosystem is brilliant and something I'd like to see in more languages targeting javascript.

Nevertheless, the learning is curve with the latter has been significantly steeper and at places the error messages are bizarrely confusing. Thus, I am not yet fully convinced that for a bulk of frontend applications (I mostly work on enterprise applications for data analysis and visualization) the benefits of that learning curve are substantially justified especially if you don't have any existing investment on the .Net side.


Many devs don't really care for the MS ecosystem. Whether this is old illogical bias or based in reality, IDK, but most of the major tech stacks that that work across ecosystems are further along on the JVM, so people go there.


F# is great for sure. You should definitely use whatever fits your needs best. I'm sure all of us will be happy just to see ML-style languages gaining greater adoption.


F# is an excellent language. I love tinkering with it. But its compiler is painfully slow compared to OCaml's, and that has a real impact on web development which is generally dependent on a fast tweak/save/refresh cycle.

Also, as I'm no longer a Windows developer, I have to say that .NET Core + F# + Mac is still not a great environment.


>why wouldn't I use F#

OCaml has functors, GADTs, better object system, nowadays it has an incredible developement pace and a huge amount of native libraries.


It's nor that hard of a sell I think... does F# compile down to javascript?


It does, there have been a couple options for a while but that had some catches but somewhat recently the Fable project came along and appears to be gaining tons of traction(for F# ecosystem) and killing it.


Thank you. I think I've heard the name Fable in relation to F#, but until this thread today, I had no idea F# compiles down to JS.


It does, though I've not used it myself so I can't comment on it personally.

http://fable.io/


I'm interested in Reason/Buckle, coming myself from the ClojureScript.

The seemingly tinier minified compilation size would be a huge plus. But what are the actual sizes emitted for large scale projects (arguably the ones that matter most for static typing)? Anyone could share real-world experiences?

For reference: I know of cases where 60K lines of clojurescript (arguably equivalent to 150K lines JS) compile down to 5MB under advanced optimization mode.

(in case that scares you: well it's an actually large app. We should do route-based code splitting soon - easy/robust with clojurescript apparently)


Hey, author here!

BuckleScript itself doesn't actually do any sort of bundling or minification of the code - in fact, it prides itself in generating "human readable" code that, worst comes to worst, one could modify by hand and not be too hung out to dry.

So in that case, you are at the mercy of the general JS ecosystem when it comes to module bundling, minification, code splitting, etc.

The Google Closure compiler does a lot of the magic behind ClojureScript's advanced optimizations, so theoretically one could leverage those same optimizations with an app compiled by BuckleScript. Unfortunately, I don't have any real-world experiences with this.

However, I do have experience using ClojureScript + Google Closure compiler and can give you a heads up that you might (...probably will) run into issues using Closure compiler with NPM libraries, which the BuckleScript ecosystem relies on.

As someone who recently started working daily with ClojureScript, I'm really crossing my fingers for some of rough edges around Node.js/ES module support in the Closure compiler to be smoothed out soon!

NINJA edit: I have heard good things about rollup with regards to dead-code elimination and other optimizations, but the JS module bundling story is moving at break-neck speed these days and I'm not really keeping up with it - Parcel's a new thing? Jaredly's writing a bundler in ReasonML?? X_X


That's a very interesting question. We could ask some Messenger and Instagram people, since they are heavily using BuckleScript. In general output JS is already fairly spartan, because BuckleScript uses a few tricks here and there, like encoding modules and records as arrays instead of objects; and completely inlining functions whenever it can.

BuckleScript also emits ES6 modules, with imports and exports, and it marks its output as either pure or impure at the module level. So potentially there's a lot of room for bundlers to do tree-shaking.

Bob Zhang, the BuckleScript team lead, is working on a new typesafe standard library for BuckleScript, which takes advantage of compile-time checks to compile to extremely minimal and idiomatic JS. Exciting times up ahead!


I have heard about the Messenger where they have 25-50% of the web client codebase in Reason, but I have not heard about the Instagram story. Can you share more info or some links about that?


Hi, about Instagram, I was mistaken about 'heavy' use. As far as I know there is one guy using Reason in Insta and from what he's said, he's found it pretty straightforward. I don't have a direct link, but if you search for 'instagram' in the ReasonML Discord chat you will find the discussion.


One thing bucklescript has going for it is that it plays nicely with the NPM/webpack ecosystem. If you want your bundled code to be optimized and minified like Clojurescript, just use a plugin/loader for webpack or your bundler of choice to run the Closure compiler or a similar javascript optimizer. Despite being more inflexible about tooling, clojurescript is great because of how it generates code specifically to take advantage of Closure's optimizaitons.


A weak point of ReasonML for me, last time I tried it, were the Promises; you have to remember to resolve them, with the compiler not providing any help. It's very easy to miss/forget to resolve them.

While it is definitely improvement over JS, it's a step back from the sense of safety you get with TS.


Hey, author here!

I definitely agree that Promises - and the whole async story in ReasonML - is pretty poor atm and ripe for improvement in the near future. I'm not sure what you mean by, "remember to resolve them," though?

I've helped Wojtek Czekalski out a bit with a small library called vow[1] that provides a more type-safe way of using Promises in BuckleScript/ReasonML - it needs a bit clean up (update to new syntax, publish to npm) that I might do in the coming weeks. Nick Cuthbert has a PR for making it completely sound[2] that might land soon as well, which might change the API but provide even more safety.

[1] https://github.com/wokalski/vow/

[2] https://github.com/wokalski/vow/pull/6


I would say it's the other way round. In ReasonML, if you forget to resolve a promise, the compiler tells you the types don't match up. This is better and more reliable than the best linting rules you can get today for JavaScript.

With TS, to be honest I'm not sure how safe it can be since it must play nice with the JavaScript rules that promises can be automagically resolved.


Nice article! I was also doing Advent Of Code[0] with ReasonML but sadly due to time constraints I didn't get any far. Still learned a lot about ReasonML, even if the solutions weren't really idiosyncratic! Definitely going to dive into ReasonML later again.

[0] https://github.com/petetnt/advent-of-code-2017-reasonml


How does ReasonML/Bucklescript stack up against F#/Fable. Is the only difference that F# has the .NET environment?


Good question. I would say the differences are:

- BuckleScript targets ES5 (+ES6 modules) directly, while Fable targets ES2015 (and beyond) and relies on Babel to transpile its result to ES5

- BuckleScript/ReasonML needs only NodeJS/npm to work for JavaScript compiles (but you can get the opam compiler/package manager if you want to do native development)

- BuckleScript/ReasonML has a more powerful traditional OCaml type system with higher-level abstraction features like functors and generalised algebraic data types, while Fable relies more on OOP for abstraction

- At the moment at least, BuckleScript's JS output is far more minimal than Fable's–try defining a simple record type like `type person = {id: int}` in both their online playgrounds to see the difference–it's pretty striking

- But Fable does have an open GitHub issue talking about minimising their output to be more BuckleScript-like, so it might catch up

- BuckleScript's JavaScript interop is just as powerful if not more, but does require a shift in thinking because its premise is to convert JavaScript idioms into OCaml idioms


Thanks for this, great explanation(and as a F# looks fair). I'll try out ReasonML one of these weekends, thank you.


I like the idea of Reason, but I currently do much more server coding than front end. The native compiler is currently classified as work-in-progress (https://reasonml.github.io/docs/en/native.html). I also wonder about how the community evolves if javascript-targeted reason libraries aren't compatible with native reason libraries. For instance, would a wrapper for a js promise library be able to work in server code? I'm interested in the language, but currently not investing time in it.


There are definitely individuals exploring the native-compilation story, for instance bsb-native[0] allows BuckleScript to use OCaml's native compilation tools. Jared Forsyth has also been publishing a lot of material[1] about creating cross-platform project using ReasonML.

The ReasonML team seem to be taking a conservative approach towards what they officially release. They want to make sure that they have a really good plan on how and where to move forward with each of these stories - async, native compilation, cross-platform project, optimizations, etc. Right now they seem to be focusing on creating a really high quality platform for building front-end web applications, but all of these things are on their mind.

I'm actually reminded of the fact that Jordan Walke (initial creator of React) is currently working on a native OCaml/Reason package manager called esy[2], which in my mind is kind of the starting point of the native compilation story: unifying the package and build system of the two ecosystems.

[0]: https://github.com/bsansouci/bsb-native

[1]: https://jaredforsyth.com/

[2]: https://github.com/esy/esy


The standard OCaml native compile toolchain supports Reason: http://jbuilder.readthedocs.io/en/latest/overview.html?highl...

You can write in Reason syntax and deploy native binaries with Docker: https://medium.com/@bobbypriambodo/lightweight-ocaml-docker-...

JS and native differences will probable be resolved just like with any other language that supports both: packages for common code, with specialised packages targeting specific platforms and having dependencies on the common packages.


It's fully compatible with nodejs, so super feasible to do backend dev


Has anyone actually done this in a real app? The last time I looked for nodejs examples, I could only find small POCs. The vast majority of ReasonML material seems focused on the front-end.


I ran all of my Advent of Code[0] solutions in Node.js - there's nothing specific really about running a ReasonML app in Node.js vs the browser. Except you don't need a module bundler for the former. :)

I've also been slowly working on a small CLI app using ReasonML, ReasonReact and react-blessed.

There definitely is a dearth of ReasonML server-side examples, libraries and frameworks, though - especially compared to all the front-end chatter. bs-express[1] is actually quite nice, but hasn't seen much attention from the larger community. I would highly recommend it if it's something you're interested in pursuing.

[0]: https://github.com/Lokeh/advent-2017

[1]: https://github.com/reasonml-community/bs-express


There's definitely activity on the backend, especially with GraphQL, but we don't have any large success stories to report yet. Here's a very cool native-OCaml GraphQL server you can try out today though: https://github.com/andreas/ocaml-graphql-server


Whoa, I was just looking at some examples of this library and it seriously looks just like JS, only give away is the patten matching(which is a feature I wish JS had)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: