Skip to content

Instantly share code, notes, and snippets.

@ksassnowski
Last active October 15, 2021 12:50
Show Gist options
  • Save ksassnowski/2d7740e445433add5885aec68ca1eff2 to your computer and use it in GitHub Desktop.
Save ksassnowski/2d7740e445433add5885aec68ca1eff2 to your computer and use it in GitHub Desktop.
Playing around with functors in PHP
<?php
interface Functor
{
// fmap :: Functor f => (a -> b) -> f a -> f b
public function fmap(callable $fn): Functor;
}
class Fn implements Functor
{
private $fn;
public function __construct(callable $fn)
{
$this->fn = $fn;
}
/**
* Mapping over functions is just function composition!
*/
public function fmap(callable $fn): Functor
{
return new Fn(function ($arg) use ($fn) {
return call_user_func($this->fn, $fn($arg));
});
}
public function __invoke($arg)
{
return call_user_func($this->fn, $arg);
}
}
// EXAMPLE
class User
{
public $age;
public $salary;
public function __construct($age, $salary)
{
$this->age = $age;
$this->salary = $salary;
}
}
$users = [
new User(23, 430000),
new User(31, 280000),
new User(54, 580000),
new User(63, 750000),
new User(18, 230000),
];
// filterOlderThan25 :: [User] -> [User]
$filterOlderThan25 = new Fn(function (array $users) {
return array_filter($users, function (User $user) { return $user->age >= 25; });
});
// extractSalaries :: [User] -> [Int]
$extractSalaries = new Fn(function (array $users) {
return array_map(function (User $user) { return $user->salary; }, $users);
});
// calculateAverage :: [Int] -> Double
$calculateAverage = new Fn(function (array $data) {
return array_sum($data) / count($data);
});
// program :: [User] -> Double
$program = $calculateAverage
->fmap($extractSalaries)
->fmap($filterOlderThan25);
echo $program($users);
// 536666.66666667
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment