Last active
December 1, 2020 08:04
-
-
Save gcanti/087a190fe0090210b82939f4bf3a1531 to your computer and use it in GitHub Desktop.
Free Monad example, Flow and fp-ts, npm install fp-ts
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
// @flow | |
import type { Free } from 'fp-ts/lib/Free' | |
import { liftF } from 'fp-ts/lib/Free' | |
import { Identity, identity } from 'fp-ts/lib/Identity' | |
// Creating set of instructions (AST) | |
export class Write<A> { | |
+_tag: 'Write' = 'Write'; | |
+message: string; | |
+more: A; | |
constructor(message: string, more: A) { | |
this.message = message | |
this.more = more | |
} | |
} | |
export class Read<A> { | |
+_tag: 'Read' = 'Read'; | |
+more: (input: string) => A; | |
constructor(more: (input: string) => A) { | |
this.more = more | |
} | |
} | |
export type ConsoleT = <U, L, A>(x: [U, L, A]) => Console<A> | |
export type Console<A> = Write<A> | Read<A> | |
export type ConsoleF<A> = Free<ConsoleT, A> | |
// Creating the DSL | |
export const write = (message: string): ConsoleF<void> => liftF(new Write(message, undefined)) | |
export const read = (): ConsoleF<string> => liftF(new Read(a => a)) | |
// A program | |
const program = write("What's your name?") | |
.chain(() => read()) | |
.chain(name => write(`Hello ${name}!`)) | |
// Running the program | |
export function exaustive(x: empty): empty { | |
return x; | |
} | |
export function identityInterpreter<A>(fa: Console<A>): Identity<A> { | |
switch (fa._tag) { | |
case 'Write': | |
console.log(fa.message) | |
return identity.of(fa.more) | |
case 'Read': | |
return identity.of(fa.more('Giulio')) | |
} | |
return exaustive(fa) | |
} | |
program.foldFree(identity)(identityInterpreter) | |
/* | |
What's your name? | |
Hello Giulio! | |
*/ | |
// Another Interpreter | |
import { IO, io } from 'fp-ts/lib/IO' | |
export const prompt: IO<string> = new IO(() => window.prompt('')) | |
export const log = (message: string): IO<void> => new IO(() => window.alert(message)) | |
export function ioInterpreter<A>(fa: Console<A>): IO<A> { | |
switch (fa._tag) { | |
case 'Write': | |
const a = fa.more | |
return log(fa.message).map(() => a) | |
case 'Read': | |
return prompt.map(fa.more) | |
} | |
return exaustive(fa) | |
} | |
program.foldFree(io)(ioInterpreter).run() | |
/* | |
An alert, a prompt and another alert with the name you inserted will be displayed in the browser | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
WARNING: Deprecated
fp-ts
.Free
does not exist infp-ts
but infp-ts-contrib
now.