/**
* wrapIO a value in the IO monad
*/
export const wrapIO = (a: A) => new IO(() => a);
/**
* safeIO accepts a function that has side effects and wrapIOs it in an IO Monad.
*/
export const safeIO = (f: () => A) => new IO(f);
export const pure = wrapIO;
export const suspend = safeIO;
/**
* IO monadic type for containing interactions with the 'real world'.
*/
export class IO {
constructor(private effect: () => A) { }
static safeIO = safeIO;
static pure = pure;
static suspend = suspend;
static chain = (f: (a: A) => IO) => (m: IO): IO => m.chain(f);
of(v: A): IO {
return new IO(() => v);
}
map(f: (a: A) => B): IO {
return new IO(() => f(this.effect()));
}
mapIn(b: B): IO {
return this.map(() => b);
}
/**
* chain
*/
chain(f: (a: A) => IO): IO {
return new IO(() => f(this.effect()).run());
}
chainIn(b: B): IO {
return this.chain(() => wrapIO(b));
}
/**
* run
*/
run(): A {
return this.effect();
}
}