Skip to content

Instantly share code, notes, and snippets.

@Istar-Eldritch
Created July 31, 2016 22:32
Show Gist options
  • Save Istar-Eldritch/343629fa4d522960a9f19a7b54815cea to your computer and use it in GitHub Desktop.
Save Istar-Eldritch/343629fa4d522960a9f19a7b54815cea to your computer and use it in GitHub Desktop.
IO Monad Ts
import IO from './algebraic/IO';
import {readFileSync} from 'fs';
import {prop, compose} from 'ramda';
function log<T>(v: T): T {
console.log(v.toString());
return v;
}
const map = <T>(f1: (x: T) => any) => (f2: IO<T>) => {
return f2.map(f1);
};
const ioLog = toLog => IO.of(_ => log(toLog));
const readIO = file => IO.of(_ => readFileSync(file));
function fromBuffer(b: Buffer) {
return JSON.parse(b.toString());
}
const getVersion = compose(map(prop('version')), map(fromBuffer), readIO);
getVersion('package.json').flatMap(ioLog).performUnsafeIO();
import {compose} from 'ramda';
type Func1<T1, R> = (v: T1) => R;
type FuncR<T> = (...v: any[]) => T;
interface Functor<T, M> {
apply: <T1>(f: Functor<T1, T>) => Functor<T1, M>;
map: <R>(p: Func1<M, R>) => Functor<T, R>;
}
export interface Monad<T> extends Functor<any, T> {
join: () => Monad<T>;
flatMap: <R>(p: Func1<T, R>) => Monad<R>;
performUnsafeIO: FuncR<T>;
}
export default class IO<T> implements Monad<T> {
public performUnsafeIO: FuncR<T>;
constructor(fn: FuncR<T> ) {
this.performUnsafeIO = fn;
}
public apply <T1>(fn: Functor<T1, T>): Functor<T1, T> {
return fn.map(this.performUnsafeIO);
}
public map<M>(fn: FuncR<M>): IO<M> {
return new IO(compose(<FuncR<M>>fn, this.performUnsafeIO));
}
public join<R>(): IO<R> {
function unwrap(v: T | IO<any>) {
return v instanceof IO ?
unwrap(v.performUnsafeIO()) :
v;
}
return new IO(() => unwrap(this));
}
public flatMap<R>(f: Func1<T, R>): IO<R> {
return this.map(f).join<R>();
}
public static of<R>(fn: FuncR<R>): IO<R> {
return new IO(fn);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment