Skip to content

Instantly share code, notes, and snippets.

@kana-sama
Last active July 18, 2018 09:41
Show Gist options
  • Save kana-sama/387ebe03e75717652dddbb3a612a160d to your computer and use it in GitHub Desktop.
Save kana-sama/387ebe03e75717652dddbb3a612a160d to your computer and use it in GitHub Desktop.
// @flow
interface Command<A> {
run(): A;
}
class Call<A> implements Command<A> {
value: () => A;
constructor<X>(f: X => A, x: X) {
this.value = () => f(x);
}
run(): A {
return this.value();
}
}
interface Saga<A> {
run(): A;
map<B>(f: (A) => B): Saga<B>;
chain<B>(next: (A) => Saga<B>): Saga<B>;
}
class Pure<A> implements Saga<A> {
value: A;
constructor(value: A) {
this.value = value;
}
run(): A {
return this.value;
}
map<B>(f: A => B): Saga<B> {
return new Pure(f(this.value));
}
chain<B>(next: A => Saga<B>): Saga<B> {
return next(this.value);
}
}
class Next<A> implements Saga<A> {
next: () => Saga<A>;
constructor(next: () => Saga<A>) {
this.next = next;
}
static fromCommand(command: Command<A>): Saga<A> {
return new Next(() => new Pure(command.run()));
}
run(): A {
return this.next().run();
}
map<B>(f: A => B): Saga<B> {
return new Next(() => this.next().map(f));
}
chain<B>(next: A => Saga<B>): Saga<B> {
return new Next(() => next(this.next().run()));
}
}
function inc(x: number): number {
return x + 1;
}
function numberToString(x: number): string {
return `Number(${x})`;
}
console.log(
new Pure(10)
.chain(x =>
Next.fromCommand(new Call(inc, x))
.chain(y => Next.fromCommand(new Call(numberToString, y)))
.map(y => `Before: ${x}, After: ${y}`),
)
.run(),
); // Number(11)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment