Skip to content

Instantly share code, notes, and snippets.

@JosephMoniz
Created April 9, 2014 01:04
Show Gist options
  • Save JosephMoniz/10215560 to your computer and use it in GitHub Desktop.
Save JosephMoniz/10215560 to your computer and use it in GitHub Desktop.
IO.hh
<?hh // strict
namespace traitorous;
use traitorous\algebraic\Applicative;
use traitorous\algebraic\Functor;
use traitorous\algebraic\Monad;
use traitorous\algebraic\MonadOps;
final class IO<T> implements Functor<T>, Applicative<T>, Monad<T> {
public function __construct(private (function(): T) $_f) { }
public static function of($x): IO<T> {
return new IO(() ==> $x);
}
public function map<Tb>((function(T): Tb) $f): IO<Tb> {
return $this->flatMap(($a) ==> IO::of($f($a)));
}
public function ap<Tb, Tc>(Applicative<Tb> $next): Applicative<Tc> {
return $this->flatMap(($f) ==> {
invariant($f instanceof (function(Tb): Tc), "Expects callable");
return $next->map($f);
});
}
public function flatMap<Tb>((function(T): Monad<Tb>) $f): IO<Tb> {
return new IO(() ==> $f($this->unsafePerform())->unsafePerform());
}
public function unsafePerform(): T {
$redeemer = $this->_f;
return $redeemer();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment