🦋 Monas — Scala monads for javascript

Dima Doronin
2 min readAug 26, 2018

--

“To Vik Lovell who told me dragons did not exist, then led me to their lairs …”
Ken Kesey, One Flew Over the Cuckoo’s Nest

Here’s code that finds an item in a given collection:

let item = collection.find(…);
if (item !== null && typeof item !== 'undefined') {
// do something useful
...
}

In order to detect if the item was found it should be verified on null and undefined. Should look familiar to everyone, but what if there is a better way,… something like this:

collection.find(…).map(…)

Please meet 🦋 monas — scala monads for javascript.

> npm install monas

A long story short…

Monads eliminate null pointer exceptions and reduce branching (if statement) by treating results of a function as a collection rather than a nullable value. It’s more beneficial to work with an empty collection instead if null/undefined because it can be chained. Code looks more readable and this style of coding forces to write only pure functions.

Consider two coding styles:

1. Here the variable “a” is nullable:

let a = null
if (a !== null) {
return 'Hello ' + a;
}

2. Here it’s an empty collection:

[].map(a => 'Hello' + a)

The Monas library is built on the top of this concept and introduces two fundamental monads: Option<A> and Either<A, B>.

Option

Represents optional values. Instances of Option are either Some or the object None. Basic operations:

1. Create option

let a: Option<A> = option(smth);

where smth — is an instance of A or null/undefined.

2. Transform option

Let’s say A is a number and I want to add 42 and filter only positive values.

let positiveNumber = a.map(_ => _ + 42).filter(_ => _ > 0);

3. Print it out

Now I want to print the result or return -1.

let result: number = positiveNumber.getOrElse(-1);

To learn more check out repository here:
https://github.com/ddoronin/monas

P.S. Monas + React

It can be nifty to apply options to JSX templates when you want to put some if/else logic inside.

Let’s say there is a find() function that can return a nullable result:

let result: A | null = find();

Instead of doing this:

{ result  && <div>{result}</div> }
{ !result && <div>Not found.</div> }

one can treat it as an option and write a function that will return the template:

let result: Option<A> = option(findSomething());
...
// jsx
{ result
.map(res => <div>{res}</div>)
.getOrElse(<div>Not found.</div>)
}

Or using reoption it can be rewritten as:

import { Match } from ‘reoption’
...
<Match option={result}
some={res => <div>{res}</div>}
none={<div>Not found.</div>}/>

https://github.com/ddoronin/reoption

--

--