Question

Je suis en train de lire ce tutoriel sur Haskell. Ils définissent composition de fonction comme suit:

(.)                     :: (b->c) -> (a->b) -> (a->c)
f . g                   = \ x -> f (g x)

Aucun exemple n'a été fourni, que je crois me éclairer sur ce qui est défini ici.

Quelqu'un peut-il donner un exemple simple (avec explication) de la façon dont la composition de fonction est utilisée?

Était-ce utile?

La solution

composition de fonction est un moyen de « composer » ensemble deux fonctions en une seule fonction. Voici un exemple:

Disons que vous avez ces fonctions:

even :: Int -> Bool
not :: Bool -> Bool

et que vous voulez définir votre propre fonction myOdd :: Int -> Bool en utilisant les deux ci-dessus.

La façon évidente de le faire est le suivant:

myOdd :: Int -> Bool
myOdd x = not (even x)

Mais cela peut être fait en utilisant la composition plus succincte de fonction:

myOdd :: Int -> Bool
myOdd = not . even

Les fonctions de myOdd se comportent exactement les mêmes, mais le second est créé par « colle-ing » deux fonctions ensemble.

Un scénario où cela est particulièrement utile est d'éliminer la nécessité d'un lambda explicite. Par exemple:

map (\x -> not (even x)) [1..9]

peut être réécrite à:

map (not . even) [1..9]

Un peu plus court, moins de place pour les erreurs.

Autres conseils

Note côté Fun. Composition de fonction est l'équivalent d'un syllogisme en logique:

  

Tous les hommes sont mortels. Socrate est un homme. Par conséquent, Socrate est mortel.

A syllogisme compose de deux implications importantes en un seul:

(Man => Mortal), (Socrates => Man), therefore (Socrates => Mortal)

Par conséquent ...

(b -> c) -> (a -> b) -> (a -> c)

... qui est le type de la fonction de ..

composition de f et g est une fonction qui applique la première g à son argument, puis f à la valeur renvoyée par g. Il retourne alors la valeur de retour de f.

Cette identité peut être éclairante:

f (g x) = (f . g) x

Si vous avez un fond Java / C, considérez cet exemple:

int f(int x);
int g(int x);
int theComposition(int x) { return f(g(x)); }

Cet exemple est contraint, mais supposons que nous ayons

sqr x = x * x  
inc x = x + 1

et nous voulons écrire une fonction qui calcule x ^ 2 + 1. Nous pouvons écrire

xSquaredPlusOne = inc . sqr

(ce qui signifie que

xSquaredPlusOne x = (inc . sqr) x

ce qui veut dire

xSquaredPlusOne x = inc(sqr x)

puisque f = inc et g = SQR).

composition de fonction est un moyen de chaîne de deux ou plusieurs fonctions en même temps. Il est souvent comparé à bombarder la tuyauterie. Par exemple, dans un style shell Unix, vous pouvez écrire quelque chose comme

cat foo.txt | sort -n | less

Cela va cat, alimente sa sortie à sort, et alimente la sortie de celui less.

Strictement, c'est comme l'opérateur $ Haskell. Vous pourriez écrire quelque chose comme

sum $ sort $ filter (> 0) $ my_list

Notez que, contrairement à l'exemple de la coquille, ce lit de droite à gauche. Nous commençons donc par my_list en entrée, nous courons filter dessus, nous sort, puis on calcule la sum de celui-ci.

L'opérateur de la composition de fonctions, ., fait quelque chose de similaire. L'exemple ci-dessus produit nombre ; l'exemple ci-dessous produit une fonction :

sum . sort . filter (> 0)

Notez que nous ne nourrissons pas en fait une liste dans ce. Au lieu de cela, nous venons de créer une nouvelle fonction, et nous pouvons nourrir plusieurs listes différentes pour cette fonction. Par exemple, vous pouvez nommer cette fonction:

my_function = sum . sort . filter (> 0)

Ou vous pourriez le transmettre comme argument à une autre fonction:

map (sum . sort . filter (> 0)) my_lists

Vous pouvez en principe utiliser partout où vous pouvez utiliser un autre type de fonction. Il est juste un moyen rapide et facile à lire de dire « Je veux enchaîner ces fonctions ensemble ».

Dans la page HaskellWiki sur la composition de la fonction:

desort = (reverse . sort)

desort est une fonction qui trie une liste dans le sens inverse. Fondamentalement, desort nourrit les arguments de dans sort, et se nourrit alors la valeur de retour de sort dans reverse, un rendement qui. Donc, il trie, puis il renverse la liste triée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top