[PHP] Les Functors, on en parle…

[

S’il vous plaît noter que le titre est Functors (pas functions 😎 😎 ) !!

Considérons une fonction qui ne prend qu’un seul argument. Cependant, en appelant cette fonction, nous avons beaucoup plus d’informations que nous aimerions passer à cette fonction, mais nous ne pouvons pas car il n’accepte qu’un seul paramètre. Qu’est ce qui peut être fait ?

Une réponse évidente pourrait être des variables globales. Cependant, les bonnes pratiques de codage ne préconisent pas l’utilisation de variables globales et indiquent qu’elles ne doivent être utilisées que lorsqu’il n’y a pas d’autre alternative.

Les Functors sont des objets qui peuvent être traités comme s’ils étaient une fonction ou un pointeur de fonction. Les Functors sont le plus souvent utilisés avec des LIST dans un scénario comme suit:

<?php
interface Functor
{
	// fmap :: Functor f => (a -> b) -> f a -> f b
	public function fmap(callable $fn): Functor;
}

<?php

require 'IFunctor.php';
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);
	}
}

<?php

class User 
{
	public $age;
	public $salary;
	
	public function __construct($age, $salary)
	{
		$this->age = $age;
		$this->salary = $salary;
	}
}
<?php

require 'User.class.php'
require 'Fn.class.php'

$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

Article inspiré du code source Kai Sassnowski si vous avez encore des soucis pour comprendre le conception je suis disponible pour vos questions en commentaire. Je vous conseil aussi de jeter un coup d’œil par ici. A bientôt pour d’autres articles.

A propos de l'auteur

François KOBON

Trois mots pour me décrire : Code - Build - Hack. Je réponds au nom de François KOBON. Partisan passionné de technologies/innovations libre et ouverte, d'Algorithme, de Datas, des Mathématiques, tous types de sciences... et surtout d'apprentissage non conventionnel parce je suis auto-didacte. Je suis membre de la communauté Ayiyikoh que vous pouvez retrouver en ligne sur ayiyikoh.org

Ajouter un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

François KOBON

Trois mots pour me décrire : Code - Build - Hack. Je réponds au nom de François KOBON. Partisan passionné de technologies/innovations libre et ouverte, d'Algorithme, de Datas, des Mathématiques, tous types de sciences... et surtout d'apprentissage non conventionnel parce je suis auto-didacte. Je suis membre de la communauté Ayiyikoh que vous pouvez retrouver en ligne sur ayiyikoh.org

Suivez-moi

Insert math as
Block
Inline
Additional settings
Formula color
Text color
#333333
Type math using LaTeX
Preview
\({}\)
Nothing to preview
Insert