Part 1 | Part 2
Reason, also written ReasonML, is a technology that has gained considerable attention over the past several years due to its compelling developer experience and enduring resilience. A functional programming language with built-in React support, Reason also includes an efficient toolchain and JavaScript-like syntax. Today, the Reason ecosystem now powers a variety of mission-critical applications for some of the most essential services in the world, and it counts on an active and engaged open-source community that welcomes new contributors. Thanks to ReasonReact, developers working with React can also leverage Reason to improve the development and resilience of their applications. For a diverse range of enterprise use cases, Reason can be the correct choice, particularly for failsafe applications.
Reason contributor and Reason Association member Patrick Stapfer (Lead React Developer at Tag1) came on the Tag1 Team Talks show for a wide-ranging episode with Michael Meyers (Managing Director at Tag1) and your host Preston So (Editor in Chief at Tag1; Senior Director, Product Strategy at Oracle; and author of Decoupled Drupal in Practice) about the competitive advantage Reason confers upon architects of mission-critical applications that require a high threshold of resilience and stability. We spoke about some of the unique features of Reason and why many developers are adopting it in droves. In this two-part blog series, we'll cover the most salient aspects of Reason and why you should consider it for your own enterprise applications.
What is Reason?
As a functional programming language, Reason is unique in that it offers seamless interoperability with existing JavaScript. Each Reason module compiles into a spec-compliant JavaScript module. Reason's human-readable JavaScript output makes it an excellent fit to introduce to your working JavaScript or TypeScript codebase, and there are ways to facilitate interoperability with TypeScript code for access to all TypeScript types as well. As such, Reason is not what Patrick calls a "lock-in language."
Type inference
Reason's compiler is particularly intriguing given that it ensures every value and every function in the program it handles has a proper type applied. As a result, Reason developers don't have to deal with leaky "any" / "mixed" or "unknown" types, and in most situations the developer isn't required to write type annotations to make the compiler understand the code. This makes it easier for developers to just plot out code without worrying about type annotations all the time. The code is still fully typed, with less type annotation noise. This is conducted in a very strongly typed way, and this approach means that the quality of type inference offers developers insurance that runtime errors won't surface—with the exception of JavaScript interoperability hacks that introduce greater risk.
Reason's type inference is made possible through the underpinnings of the compiler, which leverages the Hindley–Milner (HN) type system, in a fashion similar to Haskell or OCaml. Because of this, Reason is endowed with the ability to take a very different approach to inserting types into JavaScript. Whereas many developers add types on the go in JavaScript applications, and the type system remains in flux as a result, this approach often makes it difficult to scale the project once the type system requires an update. In the case of Reason, developers can employ a prescriptive type system and a robust compiler with fast performance. Best of all, developers have an experience that reflects JavaScript faithfully enough to compile directly to immediately legible JavaScript.
The Reason toolchain
Originally created by Jordan Walke at Facebook, Reason is open-sourced under the MIT license and is intended to be the optimal way to write stable and type-safe React applications. Part of this process is made easier for developers thanks to what Patrick calls a "very snappy dev toolchain" that outperforms TypeScript's toolchain at any codebase size. Reason's compiler is vendored by one single NPM package, which means that upon a single installation, developers have immediate access to the compiler and the Reason language. All that's needed beyond this is a configuration file akin to TypeScript's, and compilation will proceed to the same JavaScript file name (Reason uses .re or .rei filename extensions).
According to Laslo Horvat (Senior Laravel Developer at Tag1), Laravel is an exceptionally well-positioned tool for architecting custom applications that traffic in highly complex logic. Internally, Laravel works well with Symfony and is well-structured in such a way that allows developers to focus on building in the necessary business logic itself rather than ancillary areas of the application. In addition, Laravel supports fast provisioning of new APIs, which in turn makes it a suitable choice for building single-page applications in JavaScript. And it's brisk—one of the compiler's goals is to be as performant as possible.
Without delving too deep into the details, the compiler utilizes highly aggressive strategies to isolate modules into specific compilation artifacts. The compiler also doesn't attempt to run a process, remain in watch mode, and then perform incremental builds. Instead, Reason's compiler performs a clean build very rapidly, and later, when a developer modifies a file in the codebase, it is intelligent enough to understand the relationships between files and modules in a more efficient way than other compilers. As such, if you change a single file after a warm build, the compilation step is so fast that it's barely noticeable. This differs considerably from the situation of TypeScript, whose compiler is also written in TypeScript and is therefore accompanied with the bulk of the JavaScript runtime. Such a dependency extends boot times.
Reason modules
In Reason, modules expose a manifest of functions, types, constant values, and other items key for other portions of the application. Reason modules can also contain submodules, whose nested values can be accessed through namespaces separated by the dot operator (e.g. Module.Submodule
). Though Reason supports class-based hierarchies, and object orientation is a feasible approach in Reason, the technology has a strong preference for module-based, functional paradigms.
For developers who wish to leverage solely a certain set of functions, it's possible to include a module as a dependency and then override the functionality of it. Alternatively, developers can also define an interface of a module as a module type signature and annotate the module with which the signature should comply. This means that in Reason, structurally shaped module types that are compliant with interfaces are usable. But Reason also gently nudges developers to write functions, and specific syntactic features make it easier to compose functions together than in class-based inheritance. With Reason, there is no need to create a subclass and invoke the super()
function, since you can use functional composition instead.
Reason also offers a pipe operator, which makes it possible to chain function calls together in a graceful manner. For more complex use cases, Reason developers can create a new ad-hoc function on the fly by chaining these invocations together. And since functions are first-class citizens in JavaScript by default, they are also a feature available to developers in Reason.
Why Reason?
For developers already leveraging React for their applications, a valid question is how Reason benefits certain situations in the real world and represents a better choice. Some of the scenarios in which Reason is a valuable addition to a project include difficult-to-refactor React codebases, unsatisfactory JavaScript compilation speeds on Babel and TypeScript, and the overcomplexity of TypeScript. Thanks to substantial adoption in the React community, Reason is already in use by organizations around the world for mission-critical applications that need to remain resilient and stable in every conceivable circumstance.
Fast-ED, an application for first responders that allows paramedics to assess stroke symptoms in patients, features a decision tree with certain recommendations of how paramedics should act. Such an important tool is something where an "undefined is not a function" error is impermissible. In addition, it is critical for developers to ensure that all cases in the decision tree are handled without any errors. In order to implement a similar application in TypeScript, additional steps would be necessary: a type construct of Tagged Union types, object shapes each with a type attribute for specific cases, and conditional statements to ensure proper processing.
Sotheby's is another Reason user whose online bidding app for high-value products such as fine art requires a mission-critical approach. In situations with live bidding, there can be no glitches in the user interface while inserting dollar amounts, as this would translate into blank screens while losing out on the auctioned piece. As you can see, while the tolerance for such errors or issues would be lower for applications with lower stakes, many architects with risk aversion or particular business needs are now taking a closer look at Reason and similar approaches to application development through functional programming.
Conclusion
There are many more real-world cases of Reason in settings demanding resilience that we'll examine in the second installment of this blog series. But as you can see from this overview, Reason is well-positioned as a compelling choice for React developers who need a higher caliber of resilience and stability for their applications. And thanks to Reason's unique internals, including a blazing fast compiler, graceful type inference, and a robust module system, JavaScript and TypeScript developers alike can adapt quickly to Reason's paradigms for their own implementations. In the second installment of this blog series, we'll continue our inspection of some of the case studies that have emerged in recent years, still more use cases, and a survey of the Reason community and ecosystem.
Special thanks to Patrick Stapfer for his feedback during the writing process.
Part 1 | Part 2
For all of our Laravel content, click here.
Photo by Brigitte Tohm on Unsplash.