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