# How to write a more declarative TypeScript Code? Maybe monad implementation

> Disclaimer: In this post, I will drastically simplify the concept of monads. If you already know functional programming, please don't kill me.

Monads are a core concept of functional programming but can also be useful in other paradigms. By using them, we can write code in a more declarative way, handle side effects and make sure that our code is typesafe.

That sounds great! But, why then it's not a more widespread idea?

It's because, at first glance, it looks very complicated. Even the simplest definition of a monad looks intimidating. There's a rolling joke in the functional programming community stating that:

> A monad is just a monoid in the category of endofunctors, what's the problem?

While technically true, it doesn't explain anything. It only makes things worse for us, programmers without a mathematical background.

Does it mean that we should leave monads alone, and come back to imperative programming?

Definitely not. 

## #monadsForEveryone

Think about it - do you need to understand all the details about how a car works to drive it safely?

It's the same with monads. You can use them, and even implement them by yourself, without knowing all this [nonsense](https://en.m.wikipedia.org/wiki/Abstract_nonsense) from category theory (sorry haskellers ;)).

### So what **is** a monad?

It's a data structure that encapsulates (or wraps) zero, one or more values.  All monads need to implement a `flatMap` function (sometimes also called `bind`, `chain` or `then`). Monads, depending on their type, provide also additional functionality.

There are many different types of monads, and some of them don't look very complicated. In fact, if you are a JavaScript developer, you are already using monads almost every day, without even knowing what they are! 

JavaScript in its standard library has the following monads: 
* Array (similar to a `List` monad)
* Promise (a mixed implementation of `Continuation`and `Either` monads)
* Streams (an implementation of a (wait for it...) `Stream` monad)

Sadly, it lacks the implementation of one of the most useful monads: the `Maybe` monad.

## What is a Maybe monad?

`Maybe` monad encapsulates a value that may, or may not exist.

Let's consider the following code:

```typescript
const name: string | null = localStorage.getItem('name')  
```

Since we don't know if the key `name` exists in the localStorage, we need to check every time if the `name` variable is a `null`.

Let's say we would like to make it uppercase. The code would look like this:

```typescript
const name = localStorage.getItem('name')  

if (name !== null) {
  const uppercasedName = name.toUppercase()
}

// what if the name is null?
```

That's ugly. Probably there are a few other ways to check if the value is not null. But why do we have to even check this?

Wouldn't it be better if we could just perform operations on a value if it exists?

Maybe monad to the rescue!

Let's see how a `Maybe` monad could simplify that:

```typescript
const name = Maybe.from(localStorage.getItem('name'))
  .map(v => v.toUppercase())
```

As you see, we can chain operations on the value using the `map` function (which works exactly like `Array.map`), without even worrying if the value exists - if it doesn't, the operations will not be executed.

Now you probably see some similarities with the Promise monad too.

```typescript
Maybe.from(10)
  .map(x => x + 1)
  .map(x => null)
  .map(x => {
    // this will never be executed
  })
```
vs.

```typescript
Promise.resolve(10)
  .then(v => x + 1)
  .then(v => throw new Error())
  .then(v => {
    // this will never be executed
  })
```

## How to implement Maybe in typescript?

To start, let's decide what API we will create for our monad. Since the API is not standardized, it's up to us how we will name our functions, and how we will create the monad.

Because we are working with TypeScript, we'll try to follow conventions set by other monads implemented in JS.

Since Maybe does not exist natively in JavaScript, we will borrow the naming of the values from Haskell, and reference an empty value as `nothing` and an existing value as `just`.

First, we will create a `Maybe` class and a representation of a non-existing value `Nothing`. 

```typescript
const Nothing = Symbol('Nothing')

class Maybe<T> {
  constructor(private value: T | typeof Nothing) {}
}

export default Maybe
```

Then, we will implement a "constructor" for both states of the Maybe monad: nothing and just.

```typescript
static just<T>(value: T): Maybe<T> {
  if (value === null || value === undefined) 
    return Maybe.nothing<T>()

  return new Maybe<T>(value)
}

static nothing<T>(): Maybe<T> {
  return new Maybe<T>(Nothing)
}
```

In the `just` constructor, we are checking if the provided value is `null` or `undefined` and if it is, we store `Nothing` as a value.

That way we've abstracted the null check away from the end user.

Next, we will add a `from` method just to imitate the `Array.from` behaviour, and make it nicer to work with in JS.

```typescript
static from<T>(value: T): Maybe<T> {
  return Maybe.just(value)
}
```

Now it's time to implement the `map` method.

```typescript
public map<U>(f: (value: T) => U): Maybe<U> {
  if (this.value === Nothing) return Maybe.nothing<U>()

  return Maybe.just<U>(f(this.value))
}
```

If Maybe contains an empty value in it, we do not run the function passed into the `map` method - we abort the computations and return a `Maybe` in an empty state.

However, if the value is correct, we map the value and wrap it again in the `Maybe`.

Now we need to implement a way to extract the value from `Maybe`.

We will implement a limited version of pattern matching.

```typescript
public match<U>({ just, nothing }: { just: (value: T) => U; nothing: () => U }): U {
  if (this.value === Nothing) return nothing()

  return just(this.value)
}
```

Voilà!

We can now extract the value from the `Maybe`, and we are forced to define a case where the value does not exist.

```typescript
const val = Maybe.from(100).match({
  just: x => `${x} exists!`,
  nothing: () => "Value was empty"
})
```


The last, but the most important part is implementing the `flatMap` function. It will be very useful if we need to combine two `Maybies`.

```typescript
public flatMap<U>(f: (value: T) => Maybe<U>): Maybe<U> {
  if (this.value === Nothing) return Maybe.nothing<U>()

  return f(this.value)
}
```

It's very similar to the `map` method, but this time we leave it up to the end-user to return a `Maybe` instance. That way we can `flatten` the structure and instead of having `Maybe<Maybe<number>>` we will have just `Maybe<number>`.

```typescript
const withMap = Maybe.from(4)
  .map(v => Maybe.from(v + 5)) // Maybe<Maybe<number>>

const withFlatMap = Maybe.from(4)
  .flatMap(v => Maybe.from(v + 5)) // Maybe<number>
```

And that's really it! let's see the whole code:

```typescript
const Nothing = Symbol('Nothing')

class Maybe<T> {
  constructor(private value: T | typeof Nothing) {}

  static just<T>(value: T): Maybe<T> {
    if (value === null || value === undefined) 
      return Maybe.nothing<T>()

    return new Maybe<T>(value)
  }

  static nothing<T>(): Maybe<T> {
    return new Maybe<T>(Nothing)
  }

  static from<T>(value: T): Maybe<T> {
    return Maybe.just(value)
  }

  public map<U>(f: (value: T) => U): Maybe<U> {
    if (this.value === Nothing) return Maybe.nothing<U>()

    return Maybe.just<U>(f(this.value))
  }

  public match<U>({ just, nothing }: { just: (value: T) => U; nothing: () => U }): U {
    if (this.value === Nothing) return nothing()

    return just(this.value)
  }

  public flatMap<U>(f: (value: T) => Maybe<U>): Maybe<U> {
    if (this.value === Nothing) return Maybe.nothing<U>()

    return f(this.value)
  }
}

export default Maybe
```

It isn't that much code. Now that you know how to implement it I feel obliged to tell you that you don't have to implement it every time on your own.

There are many libraries in the npm registry with this, and other monads already implemented.

My favourite is [tsmonads](https://www.npmjs.com/package/tsmonads), but I'm sure you will find many more.

## How to use `Maybe` in the real world?

In React you could store it in your `useState` hook.

Instead of doing this:

```typescript
const [value, setValue] = useState<number | null>(null)

useEffect(() => {
  setValue(100)
}, [someCondition])

return (
  <div>{value ? value : 'No value' }</div>
)
```

You could do something like this:

```typescript
const [value, setValue] = useState<Maybe<number>>(Maybe.nothing<number>());

useEffect(() => {
  setValue(Maybe.from(100));
}, [someCondition]);

return (
  <div>
    {value.match({
      just: (x) => `${x} is the value`,
      nothing: () => "There is no value"
    })}
  </div>
);
```

With that simple example the benefits seem small, but imagine that in this component you need to transform value many times, as is the case in real-life projects.

Another usecase is to Maybify functions that may return null or undefined. For example `Array.find`:

```typescript
const maybeFind = <T>(
  array: Array<T>,
  predicate: (x: T, i?: number, a?: Array<T>) => boolean
): Maybe<T> => Maybe.from(array.find(predicate))

const value = maybeFind([false, false], x => x === true)
  .match({
    just: _ => "will never be called",
    nothing: () => "not found"
  })

console.log(value) // not found
```
You can check out the code and React example here: [![Edit maybe-monad](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/maybe-monad-g4w0le?fontsize=14&hidenavigation=1&theme=dark)
## Conclusions

Don't let the monad definition scare you, you can still use Monads with all their benefits without understanding deep theory.

All you need to do is to "learn how to drive a car" and you will be able to bring the benefits of declarative programming into your programs.

`Maybe` is only one of many useful concepts drawn from functional programming. I hope that this post encourages you to learn more about this paradigm!

If so, I hope to see you again on this blog :)
