Effects

In functional programming, functions are pure. This means that they abide all the following restrictions:

  • called twice with the same arguments (including $this), the function returns the same result;
  • returning a result is the only thing the function does.

Some examples of pure functions built-in to Hack are sqrt and strlen. Counter-examples are rand and printf. rand returns a different result each time it's called, violating the first restriction. printf violates the second restriction, because it does more than just returning a result: it has an effect.

I/O actions

To deal with effects in functional programming, we defer the effects using a construct known as I/O actions. Rather than performing effects directly, we construct and compose I/O actions. I/O actions encapsulate effects. At the very end of the main script, we then invoke the final I/O action to perform the effects.

Creating I/O actions

I/O actions can be created from impure functions using the IO constructor:

<?hh // strict
use FH\IO;

function safeEcho(string $text): IO<mixed> {
    return new IO(function() use($text) {
        echo $text;
        return null;
    });
}

Is safeEcho a pure function? Why yes:

  • given the same string, it returns the same I/O action;
  • returning an I/O action is all it does.

You can also create an effectless I/O action that returns the same value every time:

$answer = IO::pure(42);

Transforming I/O actions

We can transform an I/O action to return a different result using the map method:

$name = new IO(function() {
    return file_get_contents('username.txt');
});

$canonicalName = name()->map($s ==> strtoupper($s));

We can also sequence two I/O actions using bind:

$age = (new IO(function() {
    return file_get_contents('userage.txt');
}))->map($s ==> (int)$s);

$userInfo = $name->bind($n ==> $age->map($a ==> tuple($n, $a)));

The $userInfo I/O action will read the username.txt and userage.txt files (in that order), and return a tuple of the contents of both.

Putting I/O actions to use

To perform the effect of printing the string, we call the unsafePerform method on the I/O action:

$io = safeEcho('Hello, world!');
$io->unsafePerform();

The unsafePerform method is the only impure function in Functional Hack. Use it with caution.