En termes simples, .
est la composition de fonctions, tout comme en mathématiques:
f (g x) = (f . g) x
Dans votre cas, vous créez une nouvelle fonction, sumEuler
qui pourrait également être définie comme ceci:
sumEuler x = sum (map euler (mkList x))
Le style de votre exemple est appelé style "sans point" - les arguments de la fonction sont omis. Cela rend le code plus clair dans de nombreux cas. (Il peut être difficile de grok la première fois que vous le voyez, mais vous vous y habituerez après un certain temps. C'est un idiome courant chez Haskell.)
Si vous êtes toujours confus, il peut être utile de vous rapporter .
à quelque chose comme un tube UNIX. Si f
la sortie de s devient g
l'entrée de, dont la sortie devient h
l'entrée de, vous l'écririez sur la ligne de commande comme f < x | g | h
. Dans Haskell, .
fonctionne comme UNIX |
, mais "à l'envers" - h . g . f $ x
. Je trouve cette notation très utile pour, par exemple, traiter une liste. Au lieu d'une construction lourde comme map (\x -> x * 2 + 10) [1..10]
, vous pouvez simplement écrire (+10) . (*2) <$> [1..10]
. (Et, si vous ne voulez appliquer cette fonction qu'à une seule valeur, c'est (+10) . (*2) $ 10
. Cohérent!)
Le wiki Haskell a un bon article avec plus de détails: http://www.haskell.org/haskellwiki/Pointfree
f (g x)
=(f . g) x
"?) Ou autre chose?==
place si vous vouliez un Haskell standard valide.Le . opérateur compose des fonctions. Par exemple,
a . b
Où a et b sont des fonctions est une nouvelle fonction qui exécute b sur ses arguments, puis a sur ces résultats. Votre code
sumEuler = sum . (map euler) . mkList
est exactement le même que:
sumEuler myArgument = sum (map euler (mkList myArgument))
mais, espérons-le, plus facile à lire. La raison pour laquelle il y a des parenthèses autour de map euler est que cela rend plus clair qu'il y a 3 fonctions en cours de composition: sum , map euler et mkList - map euler est une fonction unique.
la source
sum
est une fonction dans Haskell Prelude, pas un argument desumEuler
. Il a le typeNum a => [a] -> a
L'opérateur de composition de fonction
.
a le typeDonc nous avons
euler :: Int -> Int map :: (a -> b ) -> [a ] -> [b ] (map euler) :: [Int] -> [Int] mkList :: Int -> [Int] (map euler) . mkList :: Int -> [Int] sum :: Num a => [a ] -> a sum . (map euler) . mkList :: Int -> Int
Notez qu'il
Int
s'agit bien d'une instance de laNum
classe de types.la source
Le . L'opérateur est utilisé pour la composition des fonctions. Tout comme les mathématiques, si vous avez les fonctions f (x) et g (x) f. g devient f (g (x)).
map est une fonction intégrée qui applique une fonction à une liste. En mettant la fonction entre parenthèses, la fonction est traitée comme un argument. Un terme pour cela est curry . Vous devriez chercher cela.
Ce que cela fait, c'est qu'il prend une fonction avec disons deux arguments, il applique l'argument euler. (carte euler) non? et le résultat est une nouvelle fonction, qui ne prend qu'un seul argument.
somme . (carte euler). mkList est fondamentalement une manière sophistiquée de rassembler tout cela. Je dois dire que mon Haskell est un peu rouillé mais peut-être pouvez-vous assembler vous-même cette dernière fonction?
la source
Réponse courte
Code équivalent sans points, c'est juste
sumEuler = \x -> sum ((map euler) (mkList x))
ou sans le lambda
sumEuler x = sum ((map euler) (mkList x))
car le point (.) indique la composition de la fonction.
Réponse plus longue
Tout d'abord, simplifions l'application partielle de
euler
àmap
:map_euler = map euler sumEuler = sum . map_euler . mkList
Maintenant, nous n'avons que les points. Qu'est-ce que ces points indiquent?
De la source :
Ainsi
(.)
est l' opérateur de composition .Composer
En mathématiques, nous pourrions écrire la composition des fonctions, f (x) et g (x), c'est-à-dire f (g (x)), comme
qui peut être lu "f composé avec g".
Donc en Haskell, f ∘ g, ou f composé avec g, peut s'écrire:
f . g
La composition est associative, ce qui signifie que f (g (h (x))), écrite avec l'opérateur de composition, peut laisser de côté les parenthèses sans aucune ambiguïté.
Autrement dit, puisque (f ∘ g) ∘ h est équivalent à f ∘ (g ∘ h), nous pouvons simplement écrire f ∘ g ∘ h.
Faire des cercles en arrière
Pour revenir à notre simplification précédente, ceci:
sumEuler = sum . map_euler . mkList
signifie simplement qu'il
sumEuler
s'agit d'une composition non appliquée de ces fonctions:sumEuler = \x -> sum (map_euler (mkList x))
la source
L'opérateur point applique la fonction de gauche (
sum
) à la sortie de la fonction de droite. Dans votre cas, vous enchaînez plusieurs fonctions ensemble - vous passez le résultat demkList
à(map euler)
, puis le résultat de cela àsum
. Ce site présente une bonne introduction à plusieurs des concepts.la source