Created
February 21, 2021 22:26
-
-
Save md2perpe/71e3dcf22360195a23846f9808583832 to your computer and use it in GitHub Desktop.
Monads
This file contains 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
interface Thenable<a> { | |
then<b>(cont: (_: a) => Thenable<b>): Thenable<b>; | |
} | |
/* | |
run_slow_task.then((result) => { | |
do_something(result).then((new_result) => { | |
do_something_else(new_result) | |
}) | |
}) | |
*/ | |
declare function run_slow_task<a>(): Thenable<a>; | |
declare function do_something<a,b>(result: a): Thenable<b>; | |
declare function do_something_else<b,c>(new_result: b): Thenable<c>; | |
/* | |
function main<c>(): Thenable<c> { | |
return run_slow_task().then((result) => { | |
return do_something(result).then((new_result) => { | |
return do_something_else(new_result) | |
}) | |
}) | |
} | |
*/ | |
async function main() { | |
const result = await run_slow_task(); | |
const new_result = await do_something(result); | |
const final_result = await do_something_else(new_result); | |
return final_result; | |
} | |
function foo(n: number): Promise<number> | |
{ | |
return new Promise((resolve, reject) => { | |
if (n % 2 == 0) { | |
resolve(n); | |
} | |
else { | |
reject("not even"); | |
} | |
}) | |
} | |
class MyArray<T> implements Thenable<T> | |
{ | |
private array: T[]; | |
constructor(array: T[]) { | |
this.array = array; | |
} | |
then<S>(cont: (value: T) => MyArray<S>): MyArray<S> { | |
let array_of_MyArray = this.array.map(cont); | |
let result = []; | |
for (let a of array_of_MyArray) { | |
result.push(...a.array); | |
} | |
return new MyArray(result); | |
} | |
} | |
function main2() | |
{ | |
return new MyArray([1, 2, 3]).then((n) => { | |
return new MyArray([2*n, 2*n+1]); | |
}) | |
} | |
/* | |
async function main2() | |
{ | |
const n = await new MyArray([1,2,3]); | |
return await new MyArray([2*n,2*n+1]); | |
} | |
*/ | |
//console.log(main2()) | |
abstract class Maybe<T> implements Thenable<T> | |
{ | |
abstract then<S>(cont: (_: T) => Maybe<S>): Maybe<S>; | |
static give<S>(value: S): Maybe<S> { | |
return new Just<S>(value); | |
} | |
} | |
class Just<T> extends Maybe<T> | |
{ | |
private value: T; | |
constructor(value: T) { | |
super(); | |
this.value = value; | |
} | |
then<S>(cont: (_: T) => Maybe<S>): Maybe<S> { | |
return cont(this.value); | |
} | |
} | |
class Nothing<T> extends Maybe<T> | |
{ | |
constructor() { | |
super(); | |
} | |
then<S>(cont: (_: T) => Maybe<S>): Maybe<S> { | |
return new Nothing<S>(); | |
} | |
} | |
function div(x: number, y: number): Maybe<number> | |
{ | |
if (y == 0) { | |
return new Nothing(); | |
} | |
return new Just(x/y); | |
} | |
function main3() | |
{ | |
let X = Maybe.give(2); | |
let Y = Maybe.give(0); | |
let Z = Maybe.give(5); | |
return ( | |
X.then(x => // X >>= \x -> // x <- X | |
Y.then(y => // Y >>= \y -> // y <- Y | |
Z.then(z => // Z >>= \z -> // z <- Z | |
div(x, y).then(w => // div x y >>= \w -> // w <- div x y | |
div(w, z) // div w z // div w z | |
))))) | |
} | |
console.log(main3()) | |
class ContinuationMonad<r,a> implements Thenable<a> | |
{ | |
// private continuation((_: a) => r): r; | |
private continuation: (_: (_: a) => r) => r; | |
constructor(continuation: (_: (_: a) => r) => r) { | |
this.continuation = continuation; | |
} | |
static give<r,a>(value: a) { | |
return new ContinuationMonad<r,a>( | |
(then: (_: a) => r) => then(value) | |
); | |
} | |
then<b>(next: (_: a) => ContinuationMonad<r,b>): ContinuationMonad<r,b> { | |
// this.continuation: (_: (_: a) => r) => r | |
return new ContinuationMonad( | |
(c: (_: b) => r) => this.continuation( | |
(value: a) => next(value).continuation(c) | |
) | |
); | |
} | |
run(handler: (_: a) => r): r { | |
return this.continuation(handler); | |
} | |
} | |
function main4() | |
{ | |
let cm = ( | |
ContinuationMonad.give(42) .then((x: number) => | |
ContinuationMonad.give(x+13) .then((y: number) => | |
ContinuationMonad.give(y/5) | |
))); | |
cm.run(console.log); | |
} | |
main4(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment