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.