# Why I Like OCaml
People often ask me "Hey, teej, you're a cool streamer (on twitch.tv/teej_dv btw). Why do you like OCaml so much?"[^1]. Many such cases.
## Super Short Summary
- Type Inference
- Type System
## Type System: Inference
OCaml has a Hindley-Milner type system, which is just a really fancy way of saying "Everything can always only be one type a time" and "Very cool type inference". Don't let the Haskellers trick you into thinking academic words are scary - that's how they keep their monopoly on writing academic papers.
Instead, let's look at an example. The following code defines a `user` type, that has a `name` field, which contains a string and an `age` field, which contains an `int`.
```neovim {"update":true,"path":"_/code/1720462419143.ml","timestamp":1725485238759}
<pre>
<span class="-keyword">type</span> <span class="-type">user</span> <span class="Delimiter">=</span> <span class="Delimiter">{</span> <span class="-variable">name</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span><span class="Delimiter">;</span> <span class="-variable">age</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">int</span></span> <span class="Delimiter">}</span>
</pre>
```
If we write a function in the same scope, like:
```neovim {"update":true,"path":"_/code/1720462815610.ml","timestamp":1725485238474}
<pre>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">make_user</span></span> <span class="-variable">name</span> <span class="-variable">age</span> <span class="Delimiter">=</span> <span class="Delimiter">{</span> <span class="-variable">name</span><span class="Delimiter">;</span> <span class="-variable">age</span> <span class="Delimiter">}</span>
</pre>
```
The signature of the function will look like:
```neovim {"update":true,"path":"_/code/1720463027348.mli","timestamp":1725485238192}
<pre>
<span class="-keyword">type</span> <span class="-type">user</span> <span class="Delimiter">=</span> <span class="Delimiter">{</span> <span class="-variable">name</span> <span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span><span class="Delimiter">;</span> <span class="-variable">age</span> <span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">int</span></span> <span class="Delimiter">}</span>
<span class="-keyword">val</span> <span class="-variable"><span class="-function">make_user</span></span> <span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span> <span class="Delimiter">-></span> <span class="-type-builtin"><span class="-type">int</span></span> <span class="Delimiter">-></span> <span class="-type">user</span>
</pre>
```
Which is to say, pass a `string` and then an `int` and you'll get a `user` (You can read the arrows as "applications", which once again is fancy speak for "calling functions with parameters". So `make_user` takes two arguments and then returns a `user`).
> [!NOTE]
> You will **not** get any object with the fields `name` and `age`, you'll get a `user`. Now, this might not seem too interesting yet, but bear with me!
If we continue to write more functions in the same scope as the type declaration for `user`, such as `average_age`, OCaml will continue to infer the types for us!
```neovim {"update":true,"path":"_/code/1720463217798.ml","timestamp":1725485237900}
<pre>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">average_age</span></span> <span class="-variable">users</span> <span class="Delimiter">=</span>
<span class="-keyword">let</span> <span class="-variable">total_age</span> <span class="Delimiter">=</span> <span class="-module">List</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">fold_left</span></span> <span class="Delimiter">(</span><span class="-keyword">fun</span> <span class="-variable">acc</span> <span class="-variable">u</span> <span class="Delimiter">-></span> <span class="-variable">acc</span> <span class="Operator">+</span> <span class="-variable">u</span><span class="Delimiter">.</span><span class="-variable">age</span><span class="Delimiter">)</span> <span class="-number">0</span> <span class="-variable">users</span> <span class="-keyword">in</span>
<span class="-keyword">let</span> <span class="-variable">num_users</span> <span class="Delimiter">=</span> <span class="-module">List</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">length</span></span> <span class="-variable">users</span> <span class="-keyword">in</span>
<span class="-variable">total_age</span> <span class="Operator">/</span> <span class="-variable">num_users</span>
</pre>
```
^average-age
and the inferred type signature:
```neovim {"update":true,"path":"_/code/1720463253702.mli","timestamp":1725485237624}
<pre>
<span class="-keyword">val</span> <span class="-variable"><span class="-function">average_age</span></span><span class="Delimiter">:</span> <span class="-type">user</span> <span class="-type-builtin"><span class="-type">list</span></span> <span class="Delimiter">-></span> <span class="-type-builtin"><span class="-type">int</span></span>
</pre>
```
This function can **only** take a `list of users`, which we know because we access the `u.age` field in the `fold_left` in [[Why I Like OCaml#^average-age|average-age]] and we know that it must return an integer because `age` is an int. It's not possible to have the scenario like you might have in "Type"script:
If we start with a function like this:
```neovim {"update":true,"path":"_/code/1720463979332.ts","timestamp":1725485237295}
<pre>
<span class="-keyword">interface</span> <span class="-type">User</span> <span class="Delimiter">{</span> <span class="-variable">name</span><span class="Delimiter"><span class="Delimiter">:</span></span> <span class="-type-builtin">string</span><span class="Delimiter">;</span> <span class="-variable">age</span><span class="Delimiter"><span class="Delimiter">:</span></span> <span class="-type-builtin">number</span><span class="Delimiter">;</span> <span class="Delimiter">}</span>
<span class="-keyword">function</span> <span class="-variable"><span class="-function">average_age</span></span><span class="Delimiter">(</span><span class="-variable"><span class="-variable">users</span></span><span class="Delimiter"><span class="Delimiter">:</span></span> <span class="-type">User</span><span class="Delimiter">[</span><span class="Delimiter">]</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-keyword">let</span> <span class="-variable">age</span> <span class="Operator">=</span> <span class="-number">0</span><span class="Delimiter">;</span>
<span class="-keyword">for</span> <span class="Delimiter">(</span><span class="-keyword">let</span> <span class="-variable">user</span> <span class="-keyword">of</span> <span class="-variable">users</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-variable">age</span> <span class="Operator">+=</span> <span class="-variable">user</span><span class="Delimiter">.</span><span class="-variable">age</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="-keyword">return</span> <span class="-variable">age</span> <span class="Operator">/</span> <span class="-variable">users</span><span class="Delimiter">.</span><span class="-variable">length</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
</pre>
```
and then do:
```neovim {"update":true,"path":"_/code/1720464079589.ts","timestamp":1725485236959}
<pre>
<span class="-keyword">interface</span> <span class="-type">User</span> <span class="Delimiter">{</span> <span class="-variable">name</span><span class="Delimiter"><span class="Delimiter">:</span></span> <span class="-type-builtin">string</span><span class="Delimiter">;</span> <span class="-variable">age</span><span class="Delimiter"><span class="Delimiter">:</span></span> <span class="-type-builtin">number</span><span class="Delimiter">;</span> <span class="Delimiter">}</span>
<span class="-keyword">function</span> <span class="-variable"><span class="-function">average_age</span></span><span class="Delimiter">(</span><span class="-variable"><span class="-variable">users</span></span><span class="Delimiter"><span class="Delimiter">:</span></span> <span class="-type">User</span><span class="Delimiter">[</span><span class="Delimiter">]</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-keyword">let</span> <span class="-variable">age</span> <span class="Operator">=</span> <span class="-number">0</span><span class="Delimiter">;</span>
<span class="-keyword">for</span> <span class="Delimiter">(</span><span class="-keyword">let</span> <span class="-variable">user</span> <span class="-keyword">of</span> <span class="-variable">users</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="-variable">age</span> <span class="Operator">+=</span> <span class="-variable">user</span><span class="Delimiter">.</span><span class="-variable">age</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
<span class="-keyword">if</span> <span class="Delimiter">(</span><span class="-variable">age</span> <span class="Operator">></span> <span class="-number">100</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="-keyword">return</span> <span class="String">"lol types"</span><span class="Delimiter">;</span> <span class="Delimiter">}</span>
<span class="-keyword">return</span> <span class="-variable">age</span> <span class="Operator">/</span> <span class="-variable">users</span><span class="Delimiter">.</span><span class="-variable">length</span><span class="Delimiter">;</span>
<span class="Delimiter">}</span>
</pre>
```
Typescript then just says "Oh, OK. You want a function that returns a `number | string`"....
What?! No, Nobody actually wants that. And then don't get ThePrimeagen started on what you can do with `number | string` with arrays. It's not gonna be a good time for anyone. And also, I'm **NOT** going to start the twitter discourse again on whether you should annotate return types in Typescript. I don't care. I'm going to keep writing OCaml instead and trying to make it SAAS ready!!!
On a serious note, I find this kind of thing a fundamental frustration in Typescript and often leads to sprawling unions of many different types, without exhaustive checking and complex type cross pollination.
However, if you tried this in OCaml, you would get an error:
```neovim {"update":true,"path":"_/code/1721180769696.ml","timestamp":1725485236664}
<pre>
<span class="-keyword">type</span> <span class="-type">user</span> <span class="Delimiter">=</span> <span class="Delimiter">{</span> <span class="-variable">name</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span><span class="Delimiter">;</span> <span class="-variable">age</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">int</span></span> <span class="Delimiter">}</span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">average_age</span></span> <span class="-variable">users</span> <span class="Delimiter">=</span>
<span class="-keyword">let</span> <span class="-variable">total_age</span> <span class="Delimiter">=</span> <span class="-module">List</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">fold_left</span></span> <span class="Delimiter">(</span><span class="-keyword">fun</span> <span class="-variable">acc</span> <span class="-variable">u</span> <span class="Delimiter">-></span> <span class="-variable">acc</span> <span class="Operator">+</span> <span class="-variable">u</span><span class="Delimiter">.</span><span class="-variable">age</span><span class="Delimiter">)</span> <span class="-number">0</span> <span class="-variable">users</span> <span class="-keyword">in</span>
<span class="-keyword">let</span> <span class="-variable">num_users</span> <span class="Delimiter">=</span> <span class="-module">List</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">length</span></span> <span class="-variable">users</span> <span class="-keyword">in</span>
<span class="-keyword">if</span> <span class="-variable">total_age</span> <span class="Operator">></span> <span class="-number">100</span> <span class="-keyword">then</span> <span class="String">"types"</span>
<span class="-keyword">else</span> <span class="-variable">total_age</span> <span class="Operator">/</span> <span class="-variable">num_users</span>
</pre>
```
^1721180769696
Since the first returned value of this function is a string, it says that now you can't return an `int`. If we had instead declared the function must return an int, you'd get a different error:
```neovim {"update":true,"path":"_/code/1721180922826.ml","timestamp":1725485236377}
<pre>
<span class="-keyword">type</span> <span class="-type">user</span> <span class="Delimiter">=</span> <span class="Delimiter">{</span> <span class="-variable">name</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span><span class="Delimiter">;</span> <span class="-variable">age</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">int</span></span> <span class="Delimiter">}</span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">average_age</span></span> <span class="-variable">users</span> <span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">int</span></span> <span class="Delimiter">=</span>
<span class="-keyword">let</span> <span class="-variable">total_age</span> <span class="Delimiter">=</span> <span class="-module">List</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">fold_left</span></span> <span class="Delimiter">(</span><span class="-keyword">fun</span> <span class="-variable">acc</span> <span class="-variable">u</span> <span class="Delimiter">-></span> <span class="-variable">acc</span> <span class="Operator">+</span> <span class="-variable">u</span><span class="Delimiter">.</span><span class="-variable">age</span><span class="Delimiter">)</span> <span class="-number">0</span> <span class="-variable">users</span> <span class="-keyword">in</span>
<span class="-keyword">let</span> <span class="-variable">num_users</span> <span class="Delimiter">=</span> <span class="-module">List</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">length</span></span> <span class="-variable">users</span> <span class="-keyword">in</span>
<span class="-keyword">if</span> <span class="-variable">total_age</span> <span class="Operator">></span> <span class="-number">100</span> <span class="-keyword">then</span> <span class="String">"types"</span>
<span class="-keyword">else</span> <span class="-variable">total_age</span> <span class="Operator">/</span> <span class="-variable">num_users</span>
</pre>
```
^1721180922826
If you wanted to return a union of types in OCaml, we need to introduce my next favorite aspect of the type system.
## Type System: Variants
Of course, because this is programming we can't have one name for things. You may have heard of these as:
- [Tagged Unions](https://en.wikipedia.org/wiki/Tagged_union), which are related to [Disjoint Unions](https://en.wikipedia.org/wiki/Disjoint_union)
- [Rust Enums](https://doc.rust-lang.org/rust-by-example/custom_types/enum.html)
- `Sum Types`, which are related to [Algebraic Data Types](https://en.wikipedia.org/wiki/Algebraic_data_type)
- The thing I constantly complain that Golang is missing
### Enumerations
The first version of Variants we'll discuss are the simplest: they look just like simple enumerations. Consider the following.
```neovim {"update":true,"path":"_/code/1720464647402.ml","timestamp":1725485236091}
<pre>
<span class="-keyword">type</span> <span class="-type">colors</span> <span class="Delimiter">=</span>
<span class="Delimiter">|</span> <span class="Special">Red</span>
<span class="Delimiter">|</span> <span class="Special">Blue</span>
<span class="Delimiter">|</span> <span class="Special">Green</span>
</pre>
```
^1720464647402
We define a type called `colors` (not `colours`, America btw) that is really just an [Enumerated Data Type](https://ocaml.org/docs/basic-data-types#enumerated-data-types). Which is to say, a list of possible options. This isn't anything too special at first glance, even C can do this:
```neovim {"update":true,"path":"_/code/1721181811482.c","timestamp":1725485235835}
<pre>
<span class="-keyword">typedef</span> <span class="-keyword">enum</span> <span class="-type">Colors</span> <span class="Delimiter">{</span>
<span class="-variable"><span class="-constant"><span class="-constant">RED</span></span></span><span class="Delimiter">,</span>
<span class="-variable"><span class="-constant"><span class="-constant">GREEN</span></span></span><span class="Delimiter">,</span>
<span class="-variable"><span class="-constant"><span class="-constant">BLUE</span></span></span>
<span class="Delimiter">}</span> <span class="-type"><span class="-type">colors_t</span></span><span class="Delimiter">;</span>
</pre>
```
^1721181811482
However, OCaml's variants are a lot different than C's enums
```neovim {"update":true,"path":"_/code/1721182061388.ml","timestamp":1725485235545}
<pre>
<span class="-keyword">type</span> <span class="-type">color</span> <span class="Delimiter">=</span> <span class="Special">Red</span> <span class="Delimiter">|</span> <span class="Special">Green</span> <span class="Delimiter">|</span> <span class="Special">Blue</span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">print_color</span></span> <span class="Delimiter">=</span> <span class="-keyword">function</span>
<span class="Delimiter">|</span> <span class="Special">Red</span> <span class="Delimiter">-></span> <span class="-variable"><span class="-function">print_string</span></span> <span class="String">"Red"</span>
<span class="Delimiter">|</span> <span class="Special">Green</span> <span class="Delimiter">-></span> <span class="-variable"><span class="-function">print_string</span></span> <span class="String">"Green"</span>
<span class="Delimiter">|</span> <span class="Special">Blue</span> <span class="Delimiter">-></span> <span class="-variable"><span class="-function">print_string</span></span> <span class="String">"Blue"</span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">incomplete</span></span> <span class="Delimiter">=</span> <span class="-keyword">function</span>
<span class="Delimiter">|</span> <span class="Special">Red</span> <span class="Delimiter">-></span> <span class="-variable"><span class="-function">print_string</span></span> <span class="String">"Red"</span>
<span class="Delimiter">|</span> <span class="Special">Green</span> <span class="Delimiter">-></span> <span class="-variable"><span class="-function">print_string</span></span> <span class="String">"Green"</span>
</pre>
```
```neovim
```
^1721182061388
The OCaml compiler can detect both:
- That we are pattern matching against the `color` type
- That we have no matched against all the possible `color` variants.
This is great! (and of course, doesn't suffer from footgun fallthrough choices from languages like C)
### Constructors
But!! We can do more than just list an enumeration of options, we can actually store data in the variants as well! We can return to the typescript example from earlier:
```neovim {"update":true,"path":"_/code/1721182362295.ml","timestamp":1725485235262}
<pre>
<span class="-keyword">type</span> <span class="-type">user</span> <span class="Delimiter">=</span> <span class="Delimiter">{</span> <span class="-variable">name</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span><span class="Delimiter">;</span> <span class="-variable">age</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">int</span></span> <span class="Delimiter">}</span>
<span class="-keyword">type</span> <span class="-type">goofy</span> <span class="Delimiter">=</span>
<span class="Delimiter">|</span> <span class="Special">Message</span> <span class="-keyword">of</span> <span class="-type-builtin"><span class="-type">string</span></span>
<span class="Delimiter">|</span> <span class="Special">Average</span> <span class="-keyword">of</span> <span class="-type-builtin"><span class="-type">int</span></span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">average_age</span></span> <span class="-variable">users</span> <span class="Delimiter">=</span>
<span class="-keyword">let</span> <span class="-variable">total</span> <span class="Delimiter">=</span> <span class="-module">List</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">fold_left</span></span> <span class="Delimiter">(</span><span class="-keyword">fun</span> <span class="-variable">acc</span> <span class="-variable">u</span> <span class="Delimiter">-></span> <span class="-variable">acc</span> <span class="Operator">+</span> <span class="-variable">u</span><span class="Delimiter">.</span><span class="-variable">age</span><span class="Delimiter">)</span> <span class="-number">0</span> <span class="-variable">users</span> <span class="-keyword">in</span>
<span class="-keyword">let</span> <span class="-variable">num_users</span> <span class="Delimiter">=</span> <span class="-module">List</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">length</span></span> <span class="-variable">users</span> <span class="-keyword">in</span>
<span class="-keyword">match</span> <span class="-variable">total</span> <span class="-keyword">with</span>
<span class="Delimiter">|</span> <span class="-variable">total</span> <span class="-keyword">when</span> <span class="-variable">total</span> <span class="Operator">></span> <span class="-number">100</span> <span class="Delimiter">-></span> <span class="Special">Message</span> <span class="String">"wow, that's a lot of people!"</span>
<span class="Delimiter">|</span> <span class="-variable">total</span> <span class="Delimiter">-></span> <span class="Special">Average</span> <span class="Delimiter">(</span><span class="-variable">total</span> <span class="Operator">/</span> <span class="-variable">num_users</span><span class="Delimiter">)</span>
</pre>
```
^1721182362295
Now the type signature of `average_user` is:
```neovim {"update":true,"path":"_/code/1721182580809.mli","timestamp":1725485234982}
<pre>
<span class="-keyword">type</span> <span class="-type">user</span> <span class="Delimiter">=</span> <span class="Delimiter">{</span> <span class="-variable">name</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span><span class="Delimiter">;</span> <span class="-variable">age</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">int</span></span> <span class="Delimiter">}</span>
<span class="-keyword">type</span> <span class="-type">goofy</span> <span class="Delimiter">=</span>
<span class="Delimiter">|</span> <span class="Special">Message</span> <span class="-keyword">of</span> <span class="-type-builtin"><span class="-type">string</span></span>
<span class="Delimiter">|</span> <span class="Special">Average</span> <span class="-keyword">of</span> <span class="-type-builtin"><span class="-type">int</span></span>
<span class="-keyword">val</span> <span class="-variable"><span class="-function">average_age</span></span> <span class="Delimiter">:</span> <span class="-type">user</span> <span class="-type-builtin"><span class="-type">list</span></span> <span class="Delimiter">-></span> <span class="-type">goofy</span>
</pre>
```
^1721182580809
It's not `int | string`, it's **ONE TYPE**. It can **ONLY** be the `goofy` type. And anywhere that we access the `goofy` type, we **MUST** handle all the cases (or explicitly discard them).
### Polymorphism
OK, the last variation of variants I'll talk about in this post, so please stick with me!
While this kind of variant isn't **exactly** the same as generics in some other languages, I think it's a good enough starting point. Consider the following `option` type in OCaml:
```neovim {"update":true,"path":"_/code/1721183553138.ml","timestamp":1725485234693}
<pre>
<span class="-keyword">type</span> <span class="-variable">'a</span> <span class="-type-builtin"><span class="-type">option</span></span> <span class="Delimiter">=</span>
<span class="Delimiter">|</span> <span class="Special">Some</span> <span class="-keyword">of</span> <span class="-variable">'a</span>
<span class="Delimiter">|</span> <span class="Special">None</span>
</pre>
```
^1721183553138
In OCaml, the `'a` means a "type hole" - but that's basically like the `T` you would use in Typescript. So you can swap everywhere that you see `'a` with some concrete type and it would make sense. This makes the type `polymorphic` over type `'a`[^2]. Below are some examples of values that have the `'a option` type
```neovim {"update":true,"path":"_/code/1721183642179.ml","timestamp":1725485234399}
<pre>
<span class="-keyword">type</span> <span class="-variable">'a</span> <span class="-type-builtin"><span class="-type">option</span></span> <span class="Delimiter">=</span>
<span class="Delimiter">|</span> <span class="Special">Some</span> <span class="-keyword">of</span> <span class="-variable">'a</span>
<span class="Delimiter">|</span> <span class="Special">None</span>
<span class="Comment"><span class="-spell">(* Explicit type signatures for clarity, they aren't required *)</span></span>
<span class="-keyword">let</span> <span class="-variable">value1</span> <span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">int</span></span> <span class="-type-builtin"><span class="-type">option</span></span> <span class="Delimiter">=</span> <span class="Special">Some</span> <span class="-number">100</span>
<span class="-keyword">let</span> <span class="-variable">value2</span> <span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span> <span class="-type-builtin"><span class="-type">option</span></span> <span class="Delimiter">=</span> <span class="Special">Some</span> <span class="String">"CrimsonMama"</span>
<span class="-keyword">let</span> <span class="-variable">value3</span> <span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span> <span class="-type-builtin"><span class="-type">option</span></span> <span class="Delimiter">=</span> <span class="Special">None</span>
</pre>
```
^1721183642179
And here's some examples of functions that can operate on options:
```neovim {"update":true,"path":"_/code/1721232513155.ml","timestamp":1725485234117}
<pre>
<span class="-keyword">type</span> <span class="-variable">'a</span> <span class="-type-builtin"><span class="-type">option</span></span> <span class="Delimiter">=</span>
<span class="Delimiter">|</span> <span class="Special">Some</span> <span class="-keyword">of</span> <span class="-variable">'a</span>
<span class="Delimiter">|</span> <span class="Special">None</span>
<span class="Comment"><span class="-spell">(* takes a function `f` and applies it to the value inside the option *)</span></span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function"><span class="-function">map</span></span></span> <span class="-variable">f</span> <span class="Delimiter">=</span> <span class="-keyword">function</span>
<span class="Delimiter">|</span> <span class="Special">Some</span> <span class="-variable">value</span> <span class="Delimiter">-></span> <span class="Special">Some</span> <span class="Delimiter">(</span><span class="-variable"><span class="-function">f</span></span> <span class="-variable">value</span><span class="Delimiter">)</span>
<span class="Delimiter">|</span> <span class="Special">None</span> <span class="Delimiter">-></span> <span class="Special">None</span>
<span class="Comment"><span class="-spell">(* gets the value inside the option or raises an exception, like .unwrap() in rust
(panics are just bad exceptions, btw) *)</span></span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">unwrap</span></span> <span class="Delimiter">=</span> <span class="-keyword">function</span>
<span class="Delimiter">|</span> <span class="Special">Some</span> <span class="-variable">value</span> <span class="Delimiter">-></span> <span class="-variable">value</span>
<span class="Delimiter">|</span> <span class="Special">None</span> <span class="Delimiter">-></span> <span class="-variable"><span class="-function"><span class="Special">failwith</span></span></span> <span class="String">"panic! #safety"</span>
</pre>
```
^1721232513155
> [!NOTE] Possible Other Post
> If you'd like to hear more about GADTs, Polymorphic Variants, or some other more advanced OCaml type stuff, [[contact|Tell Me!]]
## Pattern Matching
OCaml's `match` statement has two properties that I miss every time I write in a different language:
- (Builtin) Exhaustiveness Checking
- Pattern Matching
### Exhaustiveness Checking
We've seen an example earlier in the [[#Enumerations]] section about how OCaml has an error when you don't match against all the possibilities for a particular expression.
```neovim {"update":true,"path":"_/code/1721239000438.ml","timestamp":1725485233828}
<pre>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">reply</span></span> <span class="Delimiter">(</span><span class="-variable">str</span> <span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span><span class="Delimiter">)</span> <span class="Delimiter">=</span>
<span class="-keyword">match</span> <span class="-variable">str</span> <span class="-keyword">with</span>
<span class="Delimiter">|</span> <span class="String">"hello"</span> <span class="Delimiter">-></span> <span class="String">"hey!"</span>
<span class="Delimiter">|</span> <span class="String">"goodbye"</span> <span class="Delimiter">-></span> <span class="String">"see you!"</span>
</pre>
```
^1721239000438
Once we include a pattern that can match any string - which is just an identifier, to capture the variable, the compiler is happy again!
```neovim {"update":true,"path":"_/code/1721239174279.ml","timestamp":1725485233537}
<pre>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">reply</span></span> <span class="Delimiter">(</span><span class="-variable">str</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span><span class="Delimiter">)</span> <span class="Delimiter">=</span>
<span class="-keyword">match</span> <span class="-variable">str</span> <span class="-keyword">with</span>
<span class="Delimiter">|</span> <span class="String">"hello"</span> <span class="Delimiter">-></span> <span class="String">"hey!"</span>
<span class="Delimiter">|</span> <span class="String">"goodbye"</span> <span class="Delimiter">-></span> <span class="String">"see you!"</span>
<span class="Delimiter">|</span> <span class="-variable">other</span> <span class="Delimiter">-></span> <span class="String">"not sure what to say"</span>
</pre>
```
^1721239174279
### Variant Matching
```neovim {"update":true,"path":"_/code/1721239371633.ml","timestamp":1725485233261}
<pre>
<span class="Comment"><span class="-spell">(* This is defined by the OCaml standard library *)</span></span>
<span class="-keyword">type</span> <span class="Delimiter">(</span><span class="-variable">'ok</span><span class="Delimiter">,</span> <span class="-variable">'err</span><span class="Delimiter">)</span> <span class="-type">result</span> <span class="Delimiter">=</span>
<span class="Delimiter">|</span> <span class="Special">Ok</span> <span class="-keyword">of</span> <span class="-variable">'ok</span>
<span class="Delimiter">|</span> <span class="Special">Error</span> <span class="-keyword">of</span> <span class="-variable">'err</span>
<span class="Comment"><span class="-spell">(* Example of how you could encode an http error *)</span></span>
<span class="-keyword">type</span> <span class="-type">http_error</span> <span class="Delimiter">=</span> <span class="Delimiter">{</span> <span class="-variable">code</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">int</span></span><span class="Delimiter">;</span> <span class="-variable">message</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span><span class="Delimiter">;</span> <span class="Delimiter">}</span>
<span class="Comment"><span class="-spell">(* Example of how you could encode an http response,
where you're just interested in the body,
and everything else is an error *)</span></span>
<span class="-keyword">type</span> <span class="-type">response</span> <span class="Delimiter">=</span> <span class="Delimiter">(</span><span class="-type-builtin"><span class="-type">string</span></span><span class="Delimiter">,</span> <span class="-type">http_error</span><span class="Delimiter">)</span> <span class="-type">result</span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">handle_response</span></span> <span class="-variable">response</span> <span class="Delimiter">=</span>
<span class="-keyword">match</span> <span class="-variable">response</span> <span class="-keyword">with</span>
<span class="Delimiter">|</span> <span class="Special">Ok</span> <span class="-variable">message</span> <span class="Delimiter">-></span>
<span class="-module">Format</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">printf</span></span> <span class="String">"Success!: <span class="SpecialChar">%s</span>"</span> <span class="-variable">message</span>
<span class="Delimiter">|</span> <span class="Special">Error</span> <span class="Delimiter">{</span> <span class="-variable">code</span> <span class="Delimiter">=</span> <span class="-number">404</span><span class="Delimiter">;</span> <span class="-variable">message</span> <span class="Delimiter">}</span> <span class="Delimiter">-></span>
<span class="-module">Format</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">printf</span></span> <span class="String">"!! 404 Not Found !! <span class="SpecialChar">%s</span>"</span> <span class="-variable">message</span><span class="Delimiter">;</span>
<span class="Delimiter">|</span> <span class="Special">Error</span> <span class="Delimiter">{</span> <span class="-variable">code</span> <span class="Delimiter">=</span> <span class="-number">418</span><span class="Delimiter">;</span> _ <span class="Delimiter">}</span> <span class="Delimiter">-></span>
<span class="-module">Format</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">printf</span></span> <span class="String">"LOL TEAPOTS"</span><span class="Delimiter">;</span>
<span class="Delimiter">|</span> <span class="Special">Error</span> <span class="-variable">err</span> <span class="Delimiter">-></span>
<span class="-module">Format</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">printf</span></span> <span class="String">"Error: <span class="SpecialChar">%d</span> - <span class="SpecialChar">%s</span><span class="SpecialChar">\n</span>"</span> <span class="-variable">err</span><span class="Delimiter">.</span><span class="-variable">code</span> <span class="-variable">err</span><span class="Delimiter">.</span><span class="-variable">message</span><span class="Delimiter">;</span>
</pre>
```
^1721239371633
## Immutability
While the Javascript community argues about whether they should use `const` or `let` (since both are a lie) OCamlers are able to trust that they have have actual, real immutability. Everything in OCaml is immutable by default
```neovim {"update":true,"path":"_/code/1721237395872.ml","timestamp":1725485232994}
<pre>
<span class="Comment"><span class="-spell">(* In this example, `age` can be *mutated* because it's marked by `mutable` *)</span></span>
<span class="-keyword">type</span> <span class="-type">mutable_user</span> <span class="Delimiter">=</span> <span class="Delimiter">{</span> <span class="-variable">name</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span><span class="Delimiter">;</span> <span class="-keyword">mutable</span> <span class="-variable">age</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">int</span></span> <span class="Delimiter">}</span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">birthday</span></span> <span class="-variable">user</span> <span class="Delimiter">=</span>
<span class="Comment"><span class="-spell">(* Note, you don't use an `=` sign here, because you are mutating the value. *)</span></span>
<span class="-variable">user</span><span class="Delimiter">.</span><span class="-variable">age</span> <span class="Operator"><-</span> <span class="-variable">user</span><span class="Delimiter">.</span><span class="-variable">age</span> <span class="Operator">+</span> <span class="-number">1</span>
</pre>
```
^1721237395872
However, if you tried to do this with a struct without the `mutable` keyword, you would be unable to do this and get an error during compilation.
```neovim
<pre>
<span class="-keyword">type</span> <span class="-type">user</span> <span class="Delimiter">=</span> <span class="Delimiter">{</span> <span class="-variable">name</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">string</span></span><span class="Delimiter">;</span> <span class="-variable">age</span><span class="Delimiter">:</span> <span class="-type-builtin"><span class="-type">int</span></span> <span class="Delimiter">}</span>
<span class="-keyword">let</span> <span class="-variable"><span class="-function">birthday</span></span> <span class="-variable">user</span> <span class="Delimiter">=</span>
<span class="-variable"><span class="DiagnosticUnderlineError">user</span></span><span class="DiagnosticUnderlineError"><span class="Delimiter">.</span><span class="-variable">age</span> <span class="Operator"><-</span> <span class="-variable">user</span><span class="Delimiter">.</span><span class="-variable">age</span> <span class="Operator">+</span> <span class="-number">1</span></span><span class="-number"></span>
<span class="DiagnosticError"> </span><span class="DiagnosticError">└──── </span><span class="DiagnosticError">The record field age is not mutable</span>
</pre>
```
(TODO: I don't actually like this sentence, it was just fun to write on stream)
The fact that the Javascript community is fighting over `const` vs `let` shows that there is value in having this supported at the language feature but (as is usual) it's implemented in the wrong way for JS, so they completely miss the point. You can never be sure if someone is going to modify the array of users (or any of the users inside of the array) when you pass that to a function - in OCaml it's just not possible to change the originally passed data structure.
```neovim {"update":true,"path":"_/code/1721237913036.js","timestamp":1725485232729}
<pre>
<span class="-keyword">const</span> <span class="-variable">x</span> <span class="Operator">=</span> <span class="Delimiter">[</span><span class="-number">1</span><span class="Delimiter">,</span> <span class="-number">2</span><span class="Delimiter">,</span> <span class="-number">3</span><span class="Delimiter">]</span><span class="Delimiter">;</span>
<span class="Comment"><span class="-spell">// You can append to the list</span></span>
<span class="-variable">x</span><span class="Delimiter">.</span><span class="-variable"><span class="-function">push</span></span><span class="Delimiter">(</span><span class="-number">4</span><span class="Delimiter">)</span><span class="Delimiter">;</span>
<span class="Comment"><span class="-spell">// You can also change the value of an element</span></span>
<span class="-variable">x</span><span class="Delimiter">[</span><span class="-number">1</span><span class="Delimiter">]</span> <span class="Operator">=</span> <span class="String">"hi"</span><span class="Delimiter">;</span>
<span class="Comment"><span class="-spell">// ... Not very `const` now, are we?</span></span>
<span class="-variable"><span class="-variable-builtin">console</span></span><span class="Delimiter">.</span><span class="-variable"><span class="-function">log</span></span><span class="Delimiter">(</span><span class="-variable">x</span><span class="Delimiter">)</span><span class="Delimiter">;</span>
</pre>
```
^1721237913036
# TODO
- Modules
- Interfaces <3
- Everything is an expression <3
- Tooling
- Incredibly fast compiler
- Community
# Conclusion
Wow, you read all of that? You'd probably like OCaml then. Come hang out with us and make it SaaS ready. There are so many fun things to build and learn!
As I've said before:
> Everything that is currently built was once not built
[^1]: Proof:
- ![[Pasted image 20240704113210.png|400]]
- ![[Pasted image 20240704123909.png|400]]
[^2]: I know that there are also `polymorphic variants` in OCaml and that they are different., but I think this is still how you would describe this kind of polymorphism.