Les Monades : Evaluation partielle

Interlude.

J’ai besoin pour le prochain chapitre d’introduire la notion d’application partielle. Cela consiste à évaluer une partie de la fonction même si je n’ai pas tous les arguments.

Soit la fonction suivante.

1
2
3
function plus($a, $b) {
   return $a + $b;
}

Que donne l’exécution ?

1
$result = plus(10);

Une erreur bien entendu, puisque il manque un argument..

Voici une fonction tirée de la librairie php-functionnal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function push(array $array, array $values)
{
    foreach ($values as $value) {
        $array[] = $value;
    }
    return $array;
}

function curryN($numberOfArguments, callable $function, array $args = [])
{
    return function () use ($numberOfArguments, $function, $args) {
        $argsLeft = $numberOfArguments - func_num_args();
        return $argsLeft <= 0
            ? call_user_func_array($function, push($args, func_get_args()))
            : curryN($argsLeft, $function, push($args, func_get_args()));
    };
}

Et maintenant reprenons ma première fonction

1
$add = curryN(2, function($a, $b) {return $a + $b;});

Maintenant réessayons notre commande

1
$add10 = $add(10);

Je n’ai pas d’erreur mais il y a mieux !

1
$result = $add10(10) // 20.

Varions encore un peu avec aucun argument

1
2
$addition = $add();
result = $addition(10,10);//20

S’il manque un argument, la fonction ne renvoie pas de résultat mais une nouvelle fonction.

On appelle cela l’évaluation partielle.

C’est plutôt pratique..

Quelques applications pratiques

On réutilise mieux les calculs.

Par exemple

1
2
$result1 = $valeurTresComplique + $valeursTresSimple1;
$result2 = $valeurTresComplique + $valeursTresSimple2;

Devient

1
2
3
$partiel = $add($valeurTresComplique);
$result1 = $partiel($valeursTresSimple1);
$result2 = $partiel($valeursTresSimple2);

C’est plus simple à tester.

Si toute les fonctions ne prennent qu’un argument, Il y a moins de cas à tester. De plus cela permet une meilleure isolation du code. Une fonction à 5-6 arguments est rarement un bon signe dans le code.

Cela permet de chainer les fonctions.

Nous allons nous servir de cette astuce pour nos monades/functors. Depuis le début on ne peux mettre qu’une seule valeur dans mon container donc comment faire pour faire des fonctions à plusieurs arguments ?

Les évaluations partielles

Il faut quand même noter que le langage PHP n’est pas génial pour le coup.

L’expression suivante en javascript est parfaitement légale.

1
result = add(10)(5);

je suis obligé d’utiliser une variable intermédiaire en PHP.

1
2
$add10= add(10);
$result = $add10(5);

Bref la syntaxe n’est pas très pratique.

Conclusion

En Haskell et OCaml l’évaluation partielle est la norme.

1
max 10 10

En fait le langage fait.

1
(max 10) 10

Transformer une fonction à plusieurs arguments en une série de fonction à un argument s’appelle la Curryfication. Cela vient du prénom de la première personne a avoir écris sur le sujet Haskell Curry. Le nom de famille doit voir dire quelque chose aussi..

Cela semble un peu compliqué et pas forcement intéressant sur les exemples que j’ai choisi. Mais dans le prochain post nous allons utiliser cette notion.

Merci de m’avoir lu.