Skip to content

Instantly share code, notes, and snippets.

@rlucha
Last active January 16, 2018 19:38
Show Gist options
  • Select an option

  • Save rlucha/bbbf458ede4f321a110a32857e5fc308 to your computer and use it in GitHub Desktop.

Select an option

Save rlucha/bbbf458ede4f321a110a32857e5fc308 to your computer and use it in GitHub Desktop.

Introduction to the why

At uSwitch we constantly strive to deliver better value for our customers faster. Ocassionally that means evaluating new tools and technologies. One technology that recently caught our attention is ReasonML. It promises a good, but not overly complex statically types language combined with very solid

Roberto is a recent Set the task mission.

Why use static typing?

Explain the conclusions / facts. that is the purpouse of the article.

ReasonML first impressions

ReasonML is an alternate syntax for OCaml that uses Bucklescript compiler backend to output JS. It comes with a set of tools focused on great Developer Experience to write type safe, functional-style programs. The resulting code achieves pretty fast performance and small bundle sizes.

At uSwitch broadband team we have been evaluating ReasonML as a candidate to get static typing on the frontend. The main questions we wanted to answer were:

  • What are the features that this new language / platform will provide us?
  • How difficult is to integrate in our workflow?
  • What does the ecosystem look like?

ReasonML features

You can expect most of OCaml features when writing a ReasonML program: Concise syntax, type inference and functional goodies like currying and pattern matching. On top of that any ReasonML module gets exported as CommonJS, so you can use your usual bundler, and publish or consume code from npm in the way you are used to.

ReasonML's type system is sound, meaning that the type system provides semantics to ensure that our code is not going to run into an error at runtime. This is a more powerful type system than Typescript, as a comparison, but it is still pragmatic enough to keep it simple and help you get things done.

Integration with our workflow

ReasonML compiler will output any .re file under the source folder that we specify to the same path under a lib/js/src directory, we can either require those files directly as any other CommonJS module or bundle them together with webpack or any other similar tool.

ReasonML compiling to CommonJS modules means that we can replace our codebase on a module by module basis and migrate in batches. Calling ReasonML functions from the outside world is just requiring the module and calling the function from JS.

Using JS functions (or any runtime value from the environment) from ReasonML requires a bit more of work. Bucklescript provides an external declaration mechanism to do exactly that. We found it to be fairly simple to use; you can reference globals, methods and even interpolate raw output so the compiler knows what to do when translating an specific token to JS. The recommended approach in the official docs is surprisingly pragmatic: when translating your JS codebase start with getting the syntax right, then add the minimum amount of bindings to get it to compile and finally get the types right.

In general we found the community has a very pragmatic approach to solving problems which feels very refreshing. They are not discussing type theory and purity in their ivory tower but trying to get the language to be used in real world scenarios.

Ecosystem and community

Investigating the ecosystem will also give us an idea on how healthy the community is, how fast the project advances and the current lifecycle the platform is in.

Area Status
Libraries Complete OCaml standard library, few ports in alpha/beta stage from other libraries
Build System Bucklescript build tools, webpack bs-loader
Package Management npm
Stack Overflow 9 questions
Error messages Elm style, very friendly
Editor Support Atom, VIM, Emacs, VSCode
Support Channels Discord ReasonML

Ports from JS libraries seem a bit lacking at the moment, prepare yourself to write quite a few bindings to interact with your current code base. On the other hand, the build system, error messages and package management are superb.

Editor support is good, making use of OCaml-merlin, you can expect to have nice overlay type hints, code completion, exhaustive pattern matching and many more things right in your editor.

Stack Overflow is just empty, but the discord community is quite active and friendly.

Beyond ReasonML documentation

ReasonML documentation does a good job explaining the syntax and the basic features, but it is lacking an overview on how the platform works as a whole. For anything beyond the simple examples you'll end up searching in google or asking in Discord.

We found the sources of information to be fragmented. To solve most of our problems we had to use a combination of different documents: the official ReasonML docs for syntax and tooling, the Bucklescript manual for JS interops (externals, default modules and some syntax not covered by ReasonML docs) and the OCaml Manual for anything not covered by the previous two sources.

This is not obvious when reading the ReasonML docs for the first time and can be a bit frustrating to realise. This is eased by great tools like ReasonML Tools and Reasonably Typed that help us to move from OCaml syntax to ReasonML and back, and to convert Flow type declarations to ReasonML.

Expect to use those tools heavily in combination with OCaml tutorials when creating your first programs.

 

ReasonML minimal config, a tool to iterate over new concepts

After understanding the pros and cons of the platform, we created a minimal build configuration to be able to get a faster development cycle. Failing fast is important when learning a new language and we don't want to be spending more time compiling than coding.

The project we created consists of a small enviroment to play with the language, you can find it here:

https://github.com/rlucha/reasonml-minimal-config

You'll need to install the ReasonML platform before the tool, just follow the step from the official Docs.

https://facebook.github.io/reason/jsWorkflow.html

This is what you can expect to find:

  • Small static http server using Browsersync
  • Bundling with webpack, including stats.json to check with any bundle analyzer
  • Source code files watching and reloading of both the bundle and the http server.
  • Production ready minified file with dead code elimination

Conclusion

In a reasonable amount of time we got a fair amount of features working, we think it will be easy enough for us to incrementally adopt the technology and get something into production, so for now we'll be using it in a pet project to gain more knowledge and we hope to get it into our main codebase eventually.

It has been one of the most pleasurable experiences we have had with languages that transpile to JS so far, and the ReasonML team has done a great job at making it approachable.

@yawaramin

Copy link
Copy Markdown

Hello, nice article. A few notes:

  • ReasonML is an alternate syntax for OCaml that you can use to output
    bytecode, native code, or JavaScript. BuckleScript is an OCaml-to-
    JavaScript compiler. ReasonML and BuckleScript work really well
    together; in fact the BuckleScript npm module bs-platform comes with
    ReasonML support built-in.
  • BuckleScript can compile modules to CommonJS, ES6, Google Closure,
    etc. module types. You have the flexibility to choose.
  • People can get pretty sensitive about 'ivory tower', I'd recommend to
    just say 'ReasonML/OCaml is pragmatic' and leave it at that.
  • Build system: as you noted, this is very flexible, you can use Webpack
    or Rollup or Browserify etc.
  • Community: there is also https://discuss.ocaml.org (online forum)
    which has a dedicated BuckleScript channel.
  • Error messages: I would say for the moment not very friendly: mostly
    you will see 'syntax error' and a line and column number which may be
    pretty far from the actual error. It takes some getting used to.
    Cheng Lou's 'Better Errors' tool is in development to help fix that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment