Created
May 25, 2018 19:27
-
-
Save md2perpe/f67e385634e72adf899517d8ab2f42f7 to your computer and use it in GitHub Desktop.
Monad example in Typescript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///////////////////////////////////////////////////////// | |
// 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