a single unit
The monadic curse is that once someone learns what monads are and how to use them, they lose the ability to explain them to other people.
We are NOT going to talk about that
The notion of Monads comes from mathematics, especially Category theory
So they will tell you that in order to understand monads, you must first learn Haskell. It's where you start, and you have to learn category theory; without those monads, they are meaningless. I think that's like saying in order to understand burritos you must first learn Spanish.
In programming, the monad was made popular by Haskell, and has been transposed into various languages, including JS. It is used as a way of containing values and controlling mutations.
fold :: Monoid m => t m -> mBut everything is OK Eyal, why do we need this new thing that we never had to use before?
Damn it, man, What problem does it aim to solve?
Example: Anytime you had to deal with a possible 'null', 'undefined' in javascript - The Maybe Monad could have helped. It's all about flow control
so,
You can think of a Monad as a container for a value or object. Arrays or Lists are a container for a collection of values, an Object is a collection of properties and sometime functions
They all have specific method that they implement ([].forEach, {}.keys(), etc)
Before we continue...
The name Identity is based on the term "identity" used for a function that simply returns the value given to it. Identity monad will effectively do the same.
const Identity = x => ({
value: () => x,
chain: f => f(x),
map: f => Identity(f(x))
});
const one = Identity(1);
/*
What will be the reply:
1. null
2. []
3. undefined
4. throw an error
*/
function funky(o) {
o = null;
}
var x = [];
funky(x);
console.info(x);The beauty of this is that the arguments passed into it cannot ever be altered or changed: it is absolutely immutable without having to use any special APIs.
This brings us to this
A core principle in FP, and Monads.
const Identity = x => ({
value: () => x,
chain: f => f(x),
map: f => Identity(f(x))
});
const one = Identity(1);
Alternative names: emit, join, valueOf
const one = Identity(1);
console.log(one.value()); // 1Alternative names: flatMap, bind
console.log(one.chain(a => a + 1)); //2one.chain(a => SomeMonad(a + 1));{Composition}
const Identity = x => ({
value: () => x,
chain: f => f(x),
map: f => Identity(f(x))
});
const one = Identity(1);
Alternative names: fMap ('functional map')
console.log(one.map(a => a + 1));const Identity = x => ({
emit: () => x,
chain: f => f(x),
map: f => Identity(f(x)),
inspect: () => `Identity(${x})`
});
Identity.of(2).map(function(two){ return two + 2 })
//=> Identity(4)
Identity.of("flamethrowers").map(function(s){ return s.toUpperCase() })
//=> Identity("FLAMETHROWERS")
Identity.of("bombs").map(_.concat(' away')).map(_.prop('length'))
//=> Identity(10)What does Map mean?
Identity.of = function(val) {
return new Identity(val);
};
const one = Identity.of(1);
Up until now we just used the pure function form, however there is a constructor common form with the use .of()
When you see .of() in the code, it's usually an indication that this is a Monad (convention..remember?)
There’s really nothing else to it. A monad is just a specification of the behavior of some functions. What those functions actually do is completely up to you.
const List = x => ({
emit: () => x,
chain: f => f(x),
map: f => List.of(f(x)),
inspect: () => `List(${x})`
});
Array like Monad
//Add new method to Monad
concat: a => List.of(x.concat(a)),
//use as
const values = List.of([1, 3, 4, 7, 10]);
values.concat([12]).inspect();
//[1, 3, 4, 7, 10, 12]//Add new method to Monad
head: () => x[0],
//use as
const values = List.of([1, 3, 4, 7, 10]);
values.head() // 1
The most known and powerfull
Remember null and undefined?
Think of this as "maybe there is a value... but maybe there is not"
const Just = (x) => ({
chain: f => f(x),
emit: () => x,
map: f => MaybeOf(f(x)),
isJust: true,
isNothing: false,
inspect: () => `Just(${x})`,
});
const Nothing = (x) => ({
chain: _ => Nothing(),
emit: () => Nothing(),
map: _ => Nothing(),
isJust: false,
isNothing: true,
inspect: () => `Nothing`,
});
const MaybeOf = x => x === null || x === undefined || x.isNothing ? Nothing() : Just(x);
const exportMaybe = {
of: MaybeOf
};
export {
exportMaybe as Maybe
}const fahrenheitToCelsius = a => (a - 32) * 0.5556;
const reading1 = 15;const temp2C = Maybe.of(reading2)
.map(fahrenheitToCelsius);
console.log(temp2C.inspect());
// > Nothing()const reading2 = null;
Let's see an example
const temp1C = Maybe.of(reading1)
.map(fahrenheitToCelsius);
console.log(temp1C.inspect()); // > Just(-9.4444)const MaybeOf = x =>
x === null ||
x === undefined ||
x.isNothing ? Nothing() : Just(x);It works and does not break, because of this
https://github.com/JasonStorey/Optional.js
// "login.js"
import Optional from 'optional-js';
// Define some simple operations
const getUserId =
username => username === 'root' ? 1234 : 0;
const verify =
userId => userId === 1234;
const login =
userId => console.log('Logging in as : ' + userId);
// Declare a potentially undefined value
const username = process.argv[2];
// Wrap username in an Optional, and build a pipeline using our operations
Optional.ofNullable(username)
.map(getUserId)
.filter(verify)
.ifPresent(login);class Maybe<T> {
private constructor(private value: T | null) {}
static of<T>(value: T) {
if (!value) {
throw Error("Provided value must not be empty");
}
return new Maybe(value);
}
static nothing<T>() {
return new Maybe<T>(null);
}
static fromValue<T>(value: T) {
return value ? Maybe.of(value) : Maybe.nothing<T>();
}
getOrElse(defaultValue: T) {
return this.value === null ? defaultValue : this.value;
}
}https://codewithstyle.info/advanced-functional-programming-in-typescript-maybe-monad/
https://wiki.haskell.org/Monad#Interesting_monads
Read more
https://jrsinclair.com/articles/2016/marvellously-mysterious-javascript-maybe-monad/
https://dev.to/airtucha/functors-and-monads-in-plain-typescript-33o1
https://codewithstyle.info/advanced-functional-programming-in-typescript-maybe-monad/
https://github.com/MostlyAdequate/mostly-adequate-guide
https://github.com/monet/monet.js
Classroom Coding with Prof. Frisby on YouTube