Skip to content

Instantly share code, notes, and snippets.

@md2perpe
Created May 25, 2018 19:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save md2perpe/f67e385634e72adf899517d8ab2f42f7 to your computer and use it in GitHub Desktop.
Save md2perpe/f67e385634e72adf899517d8ab2f42f7 to your computer and use it in GitHub Desktop.
Monad example in Typescript
/////////////////////////////////////////////////////////
// Origin: https://www.youtube.com/watch?v=t1e8gqXLbsU
// Rewritten to Typescript by md2perpe on 25 May 2018
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
// The interface of a monad
/////////////////////////////////////////////////////////
interface Then<T>
{
then<S>(next: (T) => Then<S>) : Then<S>;
}
/////////////////////////////////////////////////////////
// Monad Maybe<T>
/////////////////////////////////////////////////////////
abstract class Maybe<T>
implements Then<T>
{
abstract then<S>(next: (T) => Maybe<S>): Maybe<S>;
abstract toString(): string;
}
class Nothing<T> extends Maybe<T>
{
then<S>(next: (T) => Maybe<S>): Maybe<S>
{
return new Nothing();
}
toString()
{
return "Nothing";
}
}
class Just<T> extends Maybe<T>
{
private value : T;
constructor(value: T)
{
super();
this.value = value;
}
then<S>(next: (T) => Maybe<S>): Maybe<S>
{
return next(this.value);
}
toString()
{
return "Just(" + this.value + ")";
}
}
/////////////////////////////////////////////////////////
// Expression
/////////////////////////////////////////////////////////
abstract class Expression
{
abstract eval(): Maybe<number>;
abstract toString(): string;
}
class Value extends Expression
{
private n: number;
constructor(n: number)
{
super();
this.n = n;
}
eval()
{
return new Just(this.n);
}
toString()
{
return "Value(" + this.n + ")";
}
}
class Division extends Expression
{
private e1: Expression;
private e2: Expression;
constructor(e1: Expression, e2: Expression)
{
super();
this.e1 = e1;
this.e2 = e2;
}
eval()
{
return this.e1.eval().then((v1) => {
return this.e2.eval().then((v2) => {
return (v2 != 0) ? new Just(v1 / v2) : new Nothing();
})
});
}
toString()
{
return "Division(" + this.e1 + ", " + this.e2 + ")";
}
}
/////////////////////////////////////////////////////////
// Demo
/////////////////////////////////////////////////////////
let e: Expression;
e = new Division(new Value(12), new Value(4));
document.writeln("<p>" + e + " => " + e.eval() + "</p>");
e = new Division(new Value(12), new Division(new Value(8), new Value(2)));
document.writeln("<p>" + e + " => " + e.eval() + "</p>");
e = new Division(new Value(12), new Division(new Value(8), new Value(0)));
document.writeln("<p>" + e + " => " + e.eval() + "</p>");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment