## 1. Project Overview & Quickstart (reasonml/primitives)

# primitives

Radix Primitives is an open-source UI component library for building high-quality, accessible design systems and web apps. Maintained by @workos.

### Repository Details
- **Repository:** [reasonml/primitives](https://github.com/reasonml/primitives)
- **GitHub Stars:** ⭐ 19,148
- **Primary Language:** TypeScript

*Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.*

## 2. Official Technical Reference & Guides (reasonml/reasonml.github.io)

## File: README.md

# Reason Website

This code is used to generate https://reasonml.github.io. It pulls in files from `docs/` and `website/` to generate HTML files served on the site.

`website/` contains the JS, CSS, images and other files (and some markdown files in `blog` which are separated from `docs/`; it's not too important).

`cd website && npm install && npm run start` to start the development server & watcher.

Don't use `npm run build`. It's mostly for debugging.

In the end, we spit out normal HTML with all but a few critical JS dependencies removed, including ReactJS itself. It's a full static website: super lightweight, portable, unfancy, but good looking. And it works with JS turned off!

Two special files:

- `sidebars.json`: lists the sections.
- `siteConfig.json`: some header and i18n configs.

During your development, most changes will be picked up at each browser refresh. If you touch these two files or `blog/`, however, you'll have to restart the server to see the changes.

## Translations

The entire site can be translated via the [Crowdin project](https://crowdin.com/project/reason). This repo only has the canonical English documentation. Don't manually edit things in `i18n/`.

## Debugging

`console.log`s appear in your terminal! Since the site itself is React-free.

## Building and Deploying

Changes from the `source` branch are automatically picked into `master` branch by CI and then published.

# Building the Playground

```
cd website && npm install
```

For modifying the actual try playground source code, run `npm run bundle-try-playground:dev` to start a watcher. Once you're done, run `npm run bundle-try-playground:prod` once.

## Building with custom BuckleScript/etc

To build the actual `bsReasonReact.js`, `refmt.js`, `stdlibBundle.js`, `reasonReactBundle.js`:

You'll need to have this repository and the [BuckleScript](https://github.com/BuckleScript/bucklescript) repository cloned. These will likely be next to each other in the directory structure.

1. Inside the BuckleScript repository, follow the [Setup](https://github.com/BuckleScript/bucklescript/blob/master/CONTRIBUTING.md#setup) guide.

2. Follow the [Contributing to the BS Playground Bundle](https://github.com/BuckleScript/bucklescript/blob/7.0.1/CONTRIBUTING.md#contributing-to-the-bs-playground-bundle) guide.

3. Run `BS_PLAYGROUND=../../reasonml.github.io/website/playground/bs node scripts/repl.js`

4. Inside the `reasonml.github.io` repository, run `cd website && yarn`

5. Then run, `yarn prepare` in the same place.

6. Finally, run `node setupSomeArtifacts.js`

If this command fails, ping @chenglou in Discord.

---

## File: docs/articles-and-videos.md

---
title: Articles & Videos
---

## Videos

- [React To The Future - ReasonConf 2019](https://www.youtube.com/watch?v=5fG_lyNuEAw)
- [ReasonML: Hype or next big thing?](https://www.youtube.com/watch?v=bqNploxWpjA&t): October 2017
- [The Why and How of ReasonML](https://www.youtube.com/watch?v=j5mlMUzpE5g): October 2017
- [Critical ReasonML'ing](https://www.youtube.com/watch?v=k77aR_JyvEE): October 2017
- [Universal Reason](https://www.youtube.com/watch?v=L0xz-ILKsLE&list=PLYU6eGtVFu8ZG3yh1FfLrqHBMUXj80wgK): October 2017
- [Reason: JavaScript-flavored OCaml](https://www.youtube.com/watch?v=vTb8UU_Yjmk) July 2017
- [A Speed-date with ReasonML](https://www.youtube.com/watch?v=dKYAh8vJiSk) May 2017
- [Imperfection](https://www.youtube.com/watch?v=tCVXp6gFD8o) May 2017
- [What's in a Language?](https://www.youtube.com/watch?v=24S5u_4gx7w) April 2017
- [Taming the Meta-language](https://www.youtube.com/watch?v=_0T5OSSzxms) March 2017
- [The Age of Reason(ML)](https://www.youtube.com/watch?v=8LCmLQ1-YqQ) November 2016
- [A 5-part introduction to ReasonML](https://scrimba.com/playlist/pZ3qcV)

## General Functional Programming & Type System

- [Inference engines: 5 examples with TypeScript, Flow and Reason](https://medium.com/@javierwchavarri/inference-engines-5-examples-with-typescript-flow-and-reason-edef2f4cf2d3)
- [C# and F# approaches to illegal states](http://enterprisecraftsmanship.com/2015/09/28/c-and-f-approaches-to-illegal-states/): F# is a cousin of Reason. Great article on F#'s equivalent of variants
- [The algebra (and calculus!) of algebraic data types](https://codewords.recurse.com/issues/three/algebra-and-calculus-of-algebraic-data-types)

## Pro Links

The more dated they look, the richer the content =P

- [How variants are represented in memory](https://discuss.ocaml.org/t/lwt-core-refactored-and-documented-to-be-contributor-friendly/161/28)
- [Phantom Types in Reason](https://gist.github.com/busypeoples/3a28d039272ec3eb33ca2fc6b32dafc7): nice example for a hidden feature of Reason/OCaml
- [How OCaml type checker works](http://okmij.org/ftp/ML/generalization.html?fref=gc)
- [Detecting use-cases for GADTs in OCaml](http://mads-hartmann.com/ocaml/2015/01/05/gadt-ocaml.html)
- [Polymorphism and its limitations](http://www.polychoron.fr/ocaml-nonmanual/polymorphism.html)
- [Adding GADT to OCaml](http://www.math.nagoya-u.ac.jp/%7Egarrigue/papers/ml2011-show.pdf), [Locally abstract types vs polymorphic annotations](https://groups.google.com/forum/#!topic/ocaml-aggregation-list/-tnouSeSQoY): on GADT and locally abstract types
- [Using the Format module](https://ocaml.org/learn/tutorials/format.html) and its [docs](https://caml.inria.fr/pub/docs/manual-ocaml/libref/Format.html): great for working with the hidden gem of the OCaml stdlib

---

## File: docs/basic-structures.md

---
title: Basic Structures
---

_Quick overview: [Basic Structures](overview.md#basic-structures)_

## List

Lists are immutable, dynamically sized, homogeneous, and ordered collections
of items. It is fast to add or remove elements from the front of a list, but
random access is slow.

Reason lists have a very basic singly-linked implementation.

```reason
let listA = [1, 2, 3];
```

Add to the front using the spread operator `...`:

```reason
let listB = [0, ...listA];
let listC = [-1, 0, ...listA];
```

Concatenate lists with the `@` operator:

```reason
let listD = listA @ listB @ [7, 8];
```

### Add to end

Adding to the end of a list is slow because the built-in list is singly linked.
The expected syntax does **not** work and will not compile:

```reason
/* Syntax error */
let listB = [...listA, 100];
```

If you need to add to the end and do not care about the operation being slow,
then use the concatenate operator:

```reason
let listB = listA @ [100];
```

A common workaround that remains performant is adding to the front of the list,
then reversing the list at the end with
[`List.rev`](basic-structures.md#reverse).

### Common Functions

- List Functions: [`module List`](https://reasonml.github.io/api/List.html)

#### Map

Map over a list to change items according to some function:

```reason
let doubled = List.map(i => i * 2, list);
```

#### Fold / Reduce

Fold over a list to reduce it to one value (which may be another collection):

```reason
let max = List.fold_left(
  (result, item) => item > result ? item : result,
  initialValue,
  list,
);
```

#### Reverse

```reason
let reversed = List.rev(list);
```

#### Length

- **Important:** This is an O(n) operation, be careful when using this function.
It is not constant time.

```reason
let n = List.length(list);
```

#### Is Empty

```reason
let isEmpty = list == [];
```

### Pattern Matching

[Pattern matching](pattern-matching.md) works with lists:

```reason
switch (list) {
| [first, second, ...rest] => "at least two"
| [first, ...rest] => "at least one"
| [] => "empty"
}
```

## Array

Arrays are mutable, fixed sized, homogeneous, and ordered collections of items.
Random access on an array is fast, but changing the size of an array requires
recreating the entire structure.

```reason
let arrayA = [| 1, 2, 3 |];
```

Access elements using square brackets:

```reason
let first = arrayA[0];
let second = arrayA[1];
```

Update elements using assignment:

```reason
arrayA[2] = 23;
```

### Common Functions

- Array Functions: [`module Array`](https://reasonml.github.io/api/Array.html)

#### Map

Map over an array to change items according to some function:

```reason
let doubled = Array.map(i => i * 2, array);
```

#### Fold / Reduce

Fold over an array to reduce it to one value (which may be another collection):

```reason
let max = Array.fold_left(
  (result, item) => item > result ? item : result,
  initialValue,
  array,
);
```

#### Concatenate

```reason
let combined = Array.append(arrayA, arrayB);
let combined = Array.concat([arrayA, arrayB, arrayC]);
```

#### Length

- Unlike lists this is a constant time operation. It is safe to use anywhere.

```reason
let n = Array.length(array);
```

#### Dynamic Creation

```reason
let zeroes = Array.make(length, 0);
let squares = Array.init(length, i => i * i);
```

#### Conversion to List

```reason
let list = Array.to_list(array);
let array = Array.of_list(list);
```

### Pattern Matching

[Pattern matching](pattern-matching.md) works with arrays, but there is no
`...rest` syntax like lists have:

```reason
switch (array) {
| [||] => "empty"
| [| first |] => "exactly one"
| [| first, second |] => "exactly two"
| _ => "at least three"
};
```

## Tuple

Tuples are  immutable, constant sized, and heterogeneous collections of items.
They provide a way to group values together quickly.

```reason
let pair = (1, "hello");
let triple = ("seven", 8, '9');
```

Access specific items in a tuple using destructuring:

```reason
let (_, second) = pair;
let (first, _, third) = triple;
```

Or [pattern matching](pattern-matching.md) over a tuple:

```reason
switch (pair) {
| ("hello", name) => print_endline("Hello " ++ name);
| ("bye", name) => print_endline("Goodbye " ++ name);
| (command, _) => print_endline("Unknown command: " ++ command);
};
```

- _Note: If a tuple will have many items or be passed around often, then records
should be preferred._

## Records

Records are another basic structure that has named fields and heterogeneous
values. There is a dedicated article on records: [Records](record.md).

---

## File: docs/boolean.md

---
title: Boolean
---

This page has moved to: [Boolean](primitives.md#boolean)

---

## File: docs/community.md

---
title: Community
---

This is where we keep track of all the awesome things happening in the community.

Come say hi!

- [Discord](https://discord.gg/reasonml)
- [Forum](https://reasonml.chat)
- [Twitter](https://twitter.com/reasonml)
- [Reddit](https://www.reddit.com/r/reasonml/)
- [Stack Overflow](http://stackoverflow.com/questions/tagged/reason)
- [DEV](https://dev.to/t/reason)

## GitHub

- [Reason Org](https://github.com/reasonml)
- [Reason Community Org](https://github.com/reasonml-community)
- [Reason Editor Plugins](https://github.com/reasonml-editor)

---

## File: docs/compiling-to-js-with-jsoo.md

---
title: Js_of_ocaml
---

[Js_of_ocaml](https://ocsigen.org/js_of_ocaml/3.7.0/manual/overview)

## Template

To get started check out this [`hello-jsoo-esy`](https://github.com/jchavarri/hello-jsoo-esy) template:

```
git clone https://github.com/jchavarri/hello-jsoo-esy.git
cd hello-jsoo-esy
esy

npm install
npm run webpack
```

---

## File: docs/compiling-to-js-with-melange.md

---
title: Melange
---

One of the best ways to use Reason is by compiling it to JavaScript and running it in a web browser or on any other environment with a JavaScript runtime, such as [Node.js](https://nodejs.org), [Deno](https://deno.com), [Cloudflare Workers](https://workers.cloudflare.com).

Reason source code can be compiled to JavaScript through our partner project, [Melange](https://melange.re).

## What's Melange?

[Melange](https://melange.re) is a backend for the OCaml compiler that emits readable, modular and highly performant JavaScript code.

> Melange strives to provide the best integration with both the OCaml and JavaScript ecosystems

If you have experience with JavaScript and the ecosystem we recommend Melange, over other alternatives such as Js_of_ocaml.

## Getting started

The install guide on the Melange website shares a lot of common steps with [our installation](installation.md), check it out: [melange.re/v2.0.0/getting-started](https://melange.re/v2.0.0/getting-started).

Since [Melange v1](https://buttondown.email/anmonteiro/archive/melange-hits-v10/), Melange integrates with dune. This means that you can use dune to compile your Reason code to JavaScript and also to bytecode or native.

## Template

To get started with Reason and Melange, there's an official template:

```bash
git clone https://github.com/melange-re/melange-opam-template
cd melange-opam-template

# Create opam switch and install dependencies
make init

# In separate terminals:

make watch # Watch for reason file changes and recompile
make serve # Run the development server
```

## Manual

If you prefer to do all the steps manually, here is a step by step. Assuming you have an opam switch with OCaml 5.1.0. If not, check the [installation](installation.md#setup-a-new-environment-manually) guide.

#### Install melange

```bash
opam install melange
```

#### Create dune-project

If you don't have a `dune-project` file, create one with the following content:

```lisp
; dune-project
(dune lang 3.8)
(use melange 0.1) ; Here we enable melange to work with dune
```

#### Emit JavaScript

In your `dune` file, add a `melange.emit` stanza to emit JavaScript.

The `melange.emit` stanza tells dune to generate JavaScript files from a set of libraries and modules. In-depth documentation about this stanza can be found in the [build-system on the Melange documentation](https://melange.re/v2.0.0/build-system/#entry-points-with-melangeemit).

```lisp
; dune
(melange.emit
 (target app))
```

#### Libraries

`dune` allows to define libraries by creating a `dune` file inside a folder and adding a [`library` stanza](https://dune.readthedocs.io/en/stable/concepts/package-spec.html#libraries).

To compile a library with melange, add the `(modes melange)` stanza to the library `dune` file.

```diff
(library
  (name ui_library)
+ (modes melange)
)
```

Once you have a melange library, you can add it to the `melange.emit` stanza:
```lisp
; dune
(melange.emit
 (target app)
 (libraries ui_library))
```

#### Compile

Each time you compile the project, dune will emit JavaScript files under `_build/default/app/` (`app` comes from the `(target app)` defined under `melange.emit`).

To compile the project, run:

```bash
dune build # Compile the entire project
# or compile the melange alias (only melange.emit stanzas)
dune build @melange
```

---

## File: docs/converting-from-js.md

---
title: Converting from JS
---

This section has been moved to ReScript project: https://rescript-lang.org/docs/manual/v8.0.0/converting-from-js. More info on the transition [here](https://rescript-lang.org/blog/bucklescript-is-rebranding).

Some parts aren't relevant anymore, but the general idea is still the same. The process of introducing a new language to your project applies for Reason also.

---

## File: docs/destructuring.md

---
title: Destructuring
---

Destructuring is a concise way to extract data from a structure. Destructuring
can be used anywhere a variable name might appear.

## Tuples

```reason
let pair = (1, "Hello");

/* Destructuring */
let (one, hello) = pair;

/* Prints: Hello */
print_endline(hello);
```

## Records

Destructuring is very commonly used with [records](record.md).

```reason
type person = {
  name: string,
  age: int,
};

let alice = {
  name: "Alice",
  age: 42,
};

/* Destructuring */
let {name, age} = alice;

/* Prints: Alice */
print_endline(name);
```

- Note: When destructuring a record the type needs to be in scope or the
record needs to be explicitly annotated.

### Renaming Record Fields

While destructuring record fields, it is possible to bind variable names that
are different than the record field names:

```reason
let {name: legalName, age} = alice;

/* Prints: Alice */
print_endline(legalName);
```

## Function Arguments

```reason
/* Without destructuring */
let hello = (person) => {
  print_endline("Hello " ++ person.name);
};

/* With destructuring */
let hello = ({name}) => {
  print_endline("Hello " ++ name);
};

/* With destructuring and aliasing */
let hello = ({name: legalName}) => {
  print_endline("Hello " ++ legalName);
};
```

---

## File: docs/draft-blog-posts.md

---
title: Draft Blog Posts
---

This article captures thoughts on design decisons from our old documentation.
These may find their way into a blog post at some point in the future, for now
they will live on this page.

## Record Design Decisions

After reading the constraints in the previous sections, and if you're coming from a dynamic language background, you might be wondering why one would bother with record in the first place instead of imitating JS and use a catch-all object concept for everything.

The reason is that JavaScript objects can be _really_ slow. Some code might add fieds, remove fields, iterate over them, pass the keys themselves somewhere else, etc. The JS engines nowadays try to "guess" your object's usage patterns and sometime optimize that into a solid C++ struct, but some other time fail to do so and convert your overly dynamic object into a hash map, with a sudden >100x performance degradation (imagine an object field access needing to hash the key and traverse the hashmap to find it).

We love simplicify, but a single all-powerful data structure that is the JS object is a bit too naive. This is why Reason separates the above use-cases into record, and proper hashmap (documented later). This way, you get to leverage the consistently fast record experience, like in the above immutable update section. Field access is also guaranteed to be super fast.

"But doesn't a Reason record compile to a JS object anyway"? Yes, but those records will trigger the JS engines' optimistic object optimizations, since they see that you never tried to e.g. add or remove record fields, iterate through the keys, etc., and therefore they'll never transform your those compiled JS objects into C++ hash maps or other slow data structures. Basically, Reason's type system enforced the disciplined usage of this data structure so that you can guarantee that it will never be accidentally slow.

(And yes, we're aware that it's comical for a language feature to transform into a dynamic-looking JS object, then transformed again by the JS engines into a C++ struct, then end up where we started in the first place. Such is modern engineering.)


## Block Scope Design Decisions

Bindings can be scoped through `{}`.



```reason
let message = {
  let part1 = "hello";
  let part2 = "world";
  part1 ++ " " ++ part2
};
/* `part1` and `part2` not accessible here! */
```

```js
var message = "hello world";
```


The value of the last line of a scope is implicitly returned.

### Design Decisions

Reason's `if`, `while` and functions all use the same block scoping. The code below works **not** because of some special "if scope"; but simply because it's the same scope syntax and feature you just saw:



```reason
if (displayGreeting) {
  let message = "Enjoying the docs so far?";
  Js.log(message)
};
/* `message` not accessible here! */
```


## Pattern matching Design Decisions

The notorious [fizzbuzz problem](https://en.wikipedia.org/wiki/Fizz_buzz#Programming_interviews) strangely trips up some people, partially due its nature of paralyzing the programmer who hopes to simplify/unify the few condition branches in search of elegance where there's none. Hopefully you can see that usually, pattern-matching's
 visual conciseness [allows us to overcome decision paralysis](/try.html?reason=PQKgBAQghgzgpgEzAewHZgBYBcsAcYBcwwATsvDlAMbIJwB0yJA5sAO4CWA1h8AGIcAXoIgBXYQGIA8gGEoAWwA2YEMABQiuFjAAzIYIBG4wWAC8YABQcAlGYB8asGBicsVDJY5h5tMAGYAGjAvHyQAVlsAb0cwAB9LAAYghNtTOzAAIgFhMWEMmPiLJLAAfVT0rP18p0KS5PLM3MFquNL7ZywSDlRmEuQdEu6sK2sYgF8AbjU1HSZPYPQARjA
sZDBFhJSwaKcAKRh6RWRmCz1hI2ER0cmgA), while keeping all the benefits (and more, as you've seen) of a bunch of brute-forced `if-else`s. There's really nothing wrong with explicitly listing out all the possibilities; Pattern matching corresponds to **case analysis** in math, a valid problem-solving technique that proves to be extremely
 convenient.

Using a Reason `switch` for the first time might make you feel like you've been missing out all these years. Careful, for it might ruin other languages for you =).

If you've tried to refactor a big, nested if-else logic, you might realize it's very hard to get the logic right. On the other hand, pattern matching + tuple conceptually maps to a 2D table, where each cell can be independently filled. This ensures that whenever you need to add a case in the `switch`, you can target that and only th
at table cell, without messing other cells up.

```reason
type animal = Dog | Cat | Bird;
let result = switch (isBig, myAnimal) {
| (true, Dog) => 1
| (true, Cat) => 2
| (true, Bird) => 3
| (false, Dog | Cat) => 4
| (false, Bird) => 5
};
```

isBig \ myAnimal | Dog | Cat | Bird
-----------------|-----|-----|------
true             |  1  |  2  |  3
false            |  4  |  4  |  5

## Strings Tips & Tricks

You probably don't need to use strings as much as you did! https://twitter.com/jusrin00/status/875238742621028355

In other languages, you'd often overload the meaning of string by using it as:

- a unique id: `var BLUE_COLOR = "blue"`
- an identifier into a data structure: `var BLUE = "blue"; var RED = "red"; var colors = [BLUE, RED]`
- the name of an object field: `person["age"] = 24`
- an enum: `if (audio.canPlayType() === 'probably') {...}` [(ಠ_ಠ)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canPlayType#Return_value)
- other crazy patterns you'll soon find horrible, after getting used to Reason's alternatives.

The more you overload the poor string type, the less the type system (or a teammate) can help you! Reason provides concise, fast and maintainable types & data structures alternatives to the use-cases above (e.g. variants, in a later section).

Under native compilation, Reason strings compile to a simple representation whose performance is straightforward to analyze, at the expense of sometimes requiring manual performance tuning. For example, naively concatenating strings like `"hi " ++ "how " ++ "are " ++ "you?"` unnecessarily allocates the intermediate strings `"are you?"` and `"how are you?"` (though it might be optimized into a single string in these simple cases). In this case, prefer [`String.concat`](/api/String.html). In a way, it's somewhat nice that the traditional runtime analysis we've learned in school can finally be useful again.

Under JavaScript compilation, a Reason string maps to a JavaScript string and vice-versa, so no such above concern or analysis opportunities apply.

## Ternary Design Decisions

Reason ternary is just a sugar for the `bool` variant and a switch:

```reason
switch (isMorning) {
| true => "Good morning!"
| false => "Hello!"
}
```

If you pass that through [`refmt`](extra-goodies.md#refmt), you'd get:

```reason
isMorning ? "Good morning!" : "Hello!";
```

Interested? Here's a [blog post](https://medium.com/@chenglou/cool-things-reason-formatter-does-9e1f79e25a82) about the spirit of our `refmt`.

## Tuples

### Tips & Tricks

You'd use tuples in handy situations that pass around multiple values without too much ceremony. For example, to return many values:

```reason
let getCenterCoordinates = () => {
  let x = doSomeOperationsHere();
  let y = doSomeMoreOperationsHere();
  (x, y)
};
```

Or to "pattern-match" (covered later) on the conjunction of possibilities:

```reason
switch (isWindowOpen, isDoorOpen) { /* this is a 2-tuple */
| (true, true) => ...
| (true, false) => ...
| (false, true) => ...
| (false, false) => ...
}
```

Try to keep the usage of tuple **local**. For data structures that are long-living and passed around often, prefer a **record**, which has named fields.

A tuple type might also be called a "product type", and `(string, int)` is written as `string * int` in some places. The idea is that a tuple is really a "cartesian product"; imagine a 2D grid, with `string` on the x axis and `int` on the y axis!

The combination of tuple + `switch` is very powerful and concise, and **wipes out an entire category of bugs**. Together, they cleanly list out all the possible combinations of values. A tuple of type `(bool, bool)` indeed has `2 * 2 = 4` possibilities, and the type system asks you to cover all 4. This lends itself well to code refactors; instead of informally adding a few if-else on arbitrary values here and there, you can directly pinpoint the exact `switch` branch you need to alter, no more and no less.

### Design Decisions

The existence of tuples might seem odd for those coming from untyped languages. "Why not just use an array?"

A type system isn't all-powerful, nor should it be; some tasteful trade-offs need to be applied in order to keep the language simple, performant (both compilation and running speed) and easy to understand. Reason lists, for example, are more flexible in size; they can be concatenated, appended, sliced, etc. In return, they need to be homogenous (can only contain a single type of value per list), and random index access on them might not always be valid*. Tuple, on the other hand, through its constraint on size, is faster, gives the type system the leeway to exhaustively track all its items' types, and guarantees safe access. In general, you'll notice a few prominent, tasteful tradeoffs in a type system: record fields are fixed but can be heterogenous, while a map's fields are flexible but homogenous, etc.

A Reason tuple is typed "structurally". This means that even if you don't annotate your data with an explicit type, the compiler can still deduce it by looking at its content, its usage, etc. As long as the declarations and the usages' inferred shapes match up, you're all good!

\* It's not that the Reason type system cannot accept heterogenous, dynamically-sized lists; it actually can in some circumstances, but making such feature the default increases both the first-time learning overhead and the understandability of code. Just because the types can accomplish it doesn't mean it's always a good idea to let some pieces of code grow unboundedly complex!

## Type Design Decisions

Reason's type system is the crystallization of decades of research and engineering. Here are a few highlights:

- **Types can be inferred**. The type system deduces the types for you even if you don't manually write them down. This speeds up the prototyping phase. Additionally, editor features like [VSCode's codelens](https://github.com/jaredly/reason-language-server) in our editor integrations show you all the types while you write code.

- **The type coverage is always 100%**. We don't need a "type coverage" tool! Every piece of Reason code has a type.

- **The type system is completely "sound"**. This means that, as long as your code compiles fine, every type guarantees that it's not lying about itself. In a conventional, best-effort type system, just because the type says it's e.g. "an integer that's never null", doesn't mean it's actually never null. In contrast, a pure Reason program has no null bugs.

Many folks who come from a gradually typed community (for example, having experienced using a type system on top of JavaScript, Ruby, Python, etc.) don't understand the fuss about Reason's types "soundness". In reality, there's a big difference between these type systems that are "best effort", aka 99.9% correct, and our type system that's "sound", aka 100% correct.

Many claim that "99% is good enough". While this could be true in other domains, such claim isn't very valid for code. **Naive probability**: If your code has 100 types, 99.9% probability of correctness per type means that overall, that code's correctness is `99.9% ^ 100 = 90.4%`

Oops. That's potentially lots of false positives in the system's reported types now. Which ones are wrong though? That type system sure isn't telling you ¯\\\_(ツ)\_/¯.

### Part 2

A type system allowing type argument is basically allowing type-level functions. `list(int)` is really the `list` type function taking in the `int` type, and returning the final, concrete type you'd use in some places. You might have noticed that in other languages, this is more or less called "generics". For example, `ArrayList` in Java.

[The principle of least power](https://en.wikipedia.org/wiki/Rule_of_least_power) applies when you're trying to "Get Things Done". If the problem domain allows, definitely pick the least abstract (aka, the most concrete) solution available, so that the solution is reached faster and has fewer unstable indirections you'd have to traverse. For example, prefer types over free-form data, prefer data-driven configuration over turing-complete function calls, prefer function calls over macros, prefer macros over project forks, etc. When you constrain your domain and power, things become easier to analyze. That is, _if_ the domain is constrained enough to allow it.

When a type system is an all-encompassing aspect of your program, we need to make sure we leave enough power in order not to overly constrain your expressiveness; without "type functions", you'd end up with quite a bit of boilerplate, e.g. hard-coded `listOfInt`, `listOfString`, `listOfArrayOfFloat`, their respective helper functions, etc. However, please also make sure you don't overly abuse the power given to you through a rather powerful type system. Sometimes, it's fine to write a _little_ bit of boilerplate to reduce the need for otherwise extra powerful types. If anything, tasteful tradeoffs might show your pragmatism and judgement more than fancy types!

## Variant Design Decisions

Variants, in their many forms (polymorphic variant, open variant, GADT, etc.), are likely _the_ feature of a type system such as Reason's. The aforementioned `option` variant, for example, obliterates the need for nullable types, a major source of bugs in other languages. Philosophically speaking, a problem is composed of many possible branches/conditions. Mishandling these conditions is the majority of what we call bugs. **A type system doesn't magically eliminate bugs; it points out the unhandled conditions and asks you to cover them**\*. The ability to model "this or that" correctly is crucial.

For example, some folks wonder how the type system can safely eliminate badly formatted JSON data from propagating into their program. They don't, not by themselves! But if the parser returns the `option` type `None | Some(actualData)`, then you'd have to handle the `None` case explicitly in later call sites. That's all there is.

Performance-wise, a variant can potentially tremendously speed up your program's logic. Here's a piece of JavaScript:

```js
let data = 'dog';
if (data === 'dog') {
  ...
} else if (data === 'cat') {
  ...
} else if (data === 'bird') {
  ...
}
```

There's a linear amount of branch checking here (`O(n)`). Compare this to using a Reason variant:

```reason
type animal = Dog | Cat | Bird;
let data = Dog;
switch (data) {
| Dog => ...
| Cat => ...
| Bird => ...
}
```

The compiler sees the variant, then

1. conceptually turns them into `type animal = 0 | 1 | 2`
2. compiles `switch` to a constant-time format (`O(1)`).

You might wonder why typed functional languages are used so often for parsing; switching on a large tree efficiently and safely is pretty much the best-case scenario for variants.



Mind blown yet? Variants have a deep connection to other fields of mathematics; [See here](https://codewords.recurse.com/issues/three/algebra-and-calculus-of-algebraic-data-types) for an interesting exploration.

\* It's always nicer to design away the problem rather than resorting to a type system to cover the pitfalls; In reality, it's unrealistic to do so for every problem, or even just to understand every problem fully in order to design a solution. A type system allows you to safely make a big category of changes to codebases without needing to understand the whole thing upfront. This is great for guided exploration. In this regard, types also allow us not needing to overly design an API just to circumvent callers' simple pitfalls. They reduce the layers of abstractions needed to "get things done", which in return reduces callers' cognitive burden.