Fun with Functors and ReasonML
Tags: functional, reason, functors, datastructures
Published: 2018-04-02 14:09:48

---
title: Fun with Functors and ReasonML
published: true
tags: functional,reasonml,functors,data-structures
canonical_url: https://hackernoon.com/fun-with-functors-and-reasonml-8bb59b243e9c
cover_image: https://thepracticaldev.s3.amazonaws.com/i/k7rfmmpoyay4bmnqaaly.png
---

> Or: Reasonable functional programming with Reason, part 1:
> A short introduction to ReasonML types and functor types from a beginner.

I started to learn some functional patterns after reading [Brian Lonsdorf](https://medium.com/u/a3129fead82b)’s amazing book [“Mostly Adequate Guide to Functional Programming in JavaScript”](https://github.com/MostlyAdequate/mostly-adequate-guide). This book made me crazy about this new paradigm, that I never learned, and made me want to practice these patterns somewhere.

I found myself using it in my fun projects but never in my real-work projects — it always fell in the “most javascript programmers don’t code like this” territory. My colleagues were right, so I decided to learn a different language. Originally, it was Haskell. I started to learn it, but it was too theoretical (or “academic”) for me: I’m a very practical guy, and I like to be able to use and build software with the paradigms and languages I learn first.

So… for the last couple of days, I’ve been learning [Reason](https://reasonml.github.io/).

* * *

### Reason?

Reason, or ReasonML, is a new syntax of OCaml. It looks more like JavaScript so it is easier to get started with. And the OCaml part doesn’t need to tell you much, other than that you have a big community behind you, in a language that is here for years. OCaml has opam as their package management tool, and the community is active. Check out [awesome-ocaml](https://github.com/rizo/awesome-ocaml) to see some cool stuff from the OCaml community.

What does “a new syntax” mean? Having a new syntax for OCaml is like using CoffeeScript or transpiling newer JS syntax to older JS syntax using Babel — writing in one syntax, then compiling it to another syntax. Reason “compiles” to OCaml, and along with BuckleScript, a tool that compiles OCaml to very efficient JavaScript, you can see the chain: Reason ➡ OCaml ➡ JavaScript.

Both OCaml and Reason have a full sound (and inferred) type system, so 100% of your code is covered with types on compile time. That means fewer bugs. The inference part is amazing too; it means that you don’t have to write the types yourself. The compiler understands your code and does that for you.

For developers coming with Java-like type systems, to type systems like Reason has — note that in Reason, nulls aren’t a thing. You can’t send null as an argument for a function which wants to get a string. It’s just not possible. _It’s not that the whole concept of absence isn’t baked into Reason_, it is just that you have a special way of doing so. That way is called `option`.

### The `option` type

In Reason, you can declare types as constructors. Constructors _can_ have data in them, but it is not mandatory. Let’s take the `option` type, for instance, its declaration looks like the following:

```ocaml
type option('a) = None | Some('a)
```

Woohoo, there’s a lot going on here for first comers. Let’s go over this definition together.

First, we declare a `type`, called `option`. Then, there are the _type parameters_: that `'a` thing is called “type parameter” — it is used like Generics or Templates in languages like Java, C++, etc. This is so option can “wrap” many different types: you can have `option(int)` if you have a nullable integer, or `option(string)` if you have a nullable string! Type parameters are always prefixed with a tick (`'`), so you can’t unsee it in examples. You can have more than one type parameter — more on that later.

Then, we say that our type is a union of 2 constructors: `None`, which receives nothing as data, and `Some`, which receives data with the type `'a`, as the type parameter says.

The built-in `option` type is the way we handle absence in Reason. In Haskell, it is called `Maybe`. We always know that we receive an `option` type, and when we have an `option` type, we always have to unpack it before we use it. We unpack data with a cool feature called [pattern matching](https://reasonml.github.io/docs/en/pattern-matching.html):

```ocaml
let greet = (optionalName: option(string)) : string =>
  switch optionalName {
  | Some(name) => "Hello, " ++ name
  | None => "Who are you?"
  };

print_endline(greet(Some("Gal"))); /* prints "Hello, Gal" */ print_endline(greet(None)); /* prints "Who are you?" */
```

See how I unpack the data with ease. When I get `None`, I return a string that contains `Who are you?`. When I get `Some` with some name in it, I return `Hello, ${name}`. It may look weird that it actually works like that, but it does! ([you can click here to see what it compiles to in the Reason Try page](https://reasonml.github.io/en/try.html?reason=DYUwLgBA5gTi4QLwQBQHsAOYCWaB2AhsAHIEC2IAXBJjvigM5gzZ5QCU7E1TLbSAPgBQECAwDu2MAGMAFqlq5CJciC4BvERAA+EAMpoKKQhS6IBEAEQAJEMGBoANFYgBqVxBMgtu4vhCCVgDqsmgQBHAQAJ5oAK4A-JZaAL4A3EJCGHxgAPogeAAmwKwgKLDwYCgGRpYA4kSWnOypEAD0AFQQWaxgDFa29k4Q9cCWEO2tmdl5hcV4peXgKH7znC0dXdl9liFhEQExCWMTQA))

### Okay okay… an optional type. What is a functor?

Now that we know what is the `option` type, we can continue from here and use it as our example for the rest of the article.

A functor is a data type that can be _mapped_. That means that you can call the `map` function on it. The `map` function takes a functor and a function. Then, applies the provided function to the functor’s value (unwraps it), and wraps the result with an instance of the functor again.

You may already be familiar with [Array#map from ES5](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map): array.map(fn). This is because _Array is a functor_ that has multiple values in it. The provided function is evaluated with every value in the array, and in return, you get a new Array! By the way, in Reason, you don’t call methods on a value — that’s OOP. The way of invoking methods is to invoke a function and pass the value to it:

```ocaml
let increment = x => x + 1;
map(Array[1], increment) /* => Array[2] */
```

The option type, Just like Array, is a functor too. To understand how it would work let’s split it into its two constructors: Some and None.

What would happen if we map over `None`? I’d suggest that it should have the same behavior as mapping over an empty array: it should do nothing, it shouldn’t execute the provided function at all — it should just return `None`. For `Some`, I’d suggest that it should have the same behavior as mapping over an array with a single value. So the single value will be applied to the function, then be packed again with `Some`:

```ocaml
let increment = x => x + 1;
map(None, increment); /* => None */
map(Some(1), increment); /* => Some(2) */
```

Implementing this map function is just a couple lines of code:

```ocaml
let mapOption = (opt, fn) =>
  switch opt {
  | None => None
  | Some(value) => Some(fn(value))
  };
```

Reason’s amazing type system ensures that `fn` is a function that receives the provided option value, and returns a new option. The full type declaration for mapOption is:

```ocaml
let mapOption = (opt: option('a), fn: 'a => 'b) : option('b)
```

Let’s go over it together: we first declare a function called `mapOption` that receives an argument called `opt`, with the type of `option('a)`. As we already talked about, `'a` is a type parameter, making this function get _any type of `option`._ then, we receive a function that receives `'a` (the type parameter we had in the opt argument), and returns `'b`, which is or isn’t a different type. Then, the function returns `option('b)`, which is the same type as the inner function result type but wrapped in an `option`.

In other words, we receive an `option('a)`, then we receive a function that transforms a value from type `'a` to `'b`, and then we return `option('b)`: we support transforming between the inner types, while we’re still in `option` land:

```ocaml
let stringify = x => string_of_int(x); /* int => string */
mapOption(Some(1), stringify); /* => Some("1") */
mapOption(None, stringify); /* => None */
```

### More functor examples

We can declare another type — the `result` functor. The result functor will be almost like `option`, but its negative side will have a value too. You can treat its value as a `reason`, or `error`, or just `failure`. When you return the `result` functor, you’re basically saying that “this method may fail”. You can use result in validations and for database queries, or for anything whose error is important:

```ocaml
let result('s, 'f) = Success('s) | Failure('f)
```

The map behavior is almost identical to the `optionMap` behavior. If we have `Success`, we will take its data and apply it to the provided function. If we have a `Failure`, we wouldn’t apply the value to the function, and just leave that `Failure` as it is. The implementation, again, is a couple lines of code:

```ocaml
let mapResult = (res, fn) =>
  switch res {
  | Failure(failure) => Failure(failure)
  | Success(success) => Success(fn(success))
  };
```

This data structure helps us build our program as a tree. When we have a problem, we stop applying our logic to it. We basically stop going through the “happy path” until we handle the failure. _When we map over `Failure`, we stay with the same failure we had, so no data transformation will happen once we have a `Failure`._

In the next article, I’m going to write about Monads, a special case of Functors, that can help you a lot while building data transformations.

> Up until then, what are your ideas of custom functors?

Thanks for reading!

* * *