Created
December 20, 2018 14:51
-
-
Save hiroqn/77d92d85a149413ab94e1682c5882a66 to your computer and use it in GitHub Desktop.
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
import { Either, left, right } from 'fp-ts/lib/Either'; | |
import * as free from 'fp-ts/lib/Free'; | |
import { identity } from 'fp-ts/lib/function'; | |
import { IO } from 'fp-ts/lib/IO'; | |
import { Task } from 'fp-ts/lib/Task'; | |
import { fromIO, taskEither, TaskEither } from 'fp-ts/lib/TaskEither'; | |
import * as fs from 'fs'; | |
declare module 'fp-ts/lib/HKT' { | |
interface URI2HKT<A> { | |
Fs: FsF<A>; | |
} | |
} | |
export const FsFURI = 'Fs'; | |
export type FsFURI = typeof FsFURI; | |
export class Read<A> { | |
public readonly _tag: 'Read' = 'Read'; | |
public readonly _A!: A; | |
public readonly _URI!: FsFURI; | |
constructor(readonly path: string, readonly more: (p: string) => A) {} | |
} | |
export class Write<A> { | |
public readonly _tag: 'Write' = 'Write'; | |
public readonly _A!: A; | |
public readonly _URI!: FsFURI; | |
constructor(readonly path: string, readonly content: string, readonly more: A) {} | |
} | |
export class Show<A> { | |
public readonly _tag: 'Show' = 'Show'; | |
public readonly _A!: A; | |
public readonly _URI!: FsFURI; | |
constructor(readonly message: string, readonly more: A) {} | |
} | |
export type FsF<A> = Read<A> | Write<A> | Show<A>; | |
function read(path: string) { | |
return free.liftF(new Read(path, identity)); | |
} | |
function write(path: string, content: string) { | |
return free.liftF(new Write(path, content, undefined)); | |
} | |
function show(message: string) { | |
return free.liftF(new Show(message, undefined)); | |
} | |
function interpretTaskEither<A>(fa: FsF<A>): TaskEither<string, A> { | |
switch (fa._tag) { | |
case 'Read': | |
return new TaskEither( | |
new Task(async () => { | |
try { | |
const file = await fs.promises.readFile(fa.path, { encoding: 'utf8' }); | |
return right(fa.more(file)); | |
} catch (e) { | |
return left(`read error: ${e.message}`); | |
} | |
}), | |
); | |
case 'Write': | |
return new TaskEither( | |
new Task(async () => { | |
try { | |
await fs.promises.writeFile(fa.path, fa.content); | |
} catch (e) { | |
return left(`write error: ${e.message}`); | |
} | |
return right(fa.more); | |
}), | |
); | |
case 'Show': | |
return fromIO( | |
new IO(() => { | |
console.log(fa.message); | |
return fa.more; | |
}), | |
); | |
} | |
} | |
const program = read('./package.json').chain(content => show(content).chain(() => write('./package2.json', content))); | |
async function main() { | |
const result: Either<string, undefined> = await free | |
.foldFree(taskEither)(interpretTaskEither, program) | |
.run(); | |
if (result.isLeft()) { | |
return console.error(result.value); | |
} | |
} | |
main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment