2013-07-24 3 views
1

Salut J'ai une question sur une définition de haskell simple. J'ai une définition mais je ne la comprends pas complètement.Requête de débutant Haskell

La fonction prend une liste de fonctions et un élément et renvoie une liste formée en appliquant cette fonction.

applyAll = \fs -> \x -> map(\n -> n x) fs

Quelqu'un pourrait-il expliquer ce que Ñ et pourquoi est-fs en dehors de la fonction de carte?

Répondre

8

L'espacement vous induit en erreur. Il semble que map(\n -> n x) est un appel de fonction, mais les parenthèses ici sont pour le regroupement, pas appel de fonction. map prend deux arguments; l'appel complet est map (\n -> n x) fs, où (\n -> n x) est le premier argument (une expression lambda) et fs est le second.

Le lambda \n -> n x est une fonction qui prend une fonction en tant qu'argument et renvoie le résultat de l'application de cette fonction à x. n est l'argument ici. Le type de \n -> n x est (a -> b) -> b (où a est le type de x). Si vous avez déjà pris connaissance des sections, le lambda est équivalent à la section ($ x). Si ce n'est pas le cas, ignorez cette dernière phrase.

0

Voici une définition simple de la fonction:

f x = 2*x + 1 

Cela crée une nouvelle fonction f, qui prend un argument. Vous pouvez l'utiliser plus tard comme ceci:

main = print (f 3) 

... qui imprimerait 7. Parfois, il est commode de définir une fonction sans lui donner un nom. La syntaxe pour cela est \{- argument -} -> {- function body -}; par exemple, nous pourrions faire une version anonyme de f ci-dessus ainsi:

main = print ((\x -> 2*x + 1) 3) 

Maintenant, votre définition de applyAll fait que plusieurs fois. On pourrait nommer explicitement tout where clauses si nous voulions:

applyAll = outerMost where 
    outerMost fs = mapApply where 
     mapApply x = map applyToX fs where 
      applyToX n = n x 

... mais je pense que vous conviendrez que la verbosité supplémentaire ne fait pas les choses beaucoup plus clair! Une traduction plus naturelle (mais moins mécanique) à l'écart des fonctions anonymes ressemblerait à ceci:

applyAll fs x = map applyToX fs where 
    applyToX n = n x 

et maintenant nous espérons que cela peut presque lire comme l'anglais: appliquer toutes les fonctions fs à une valeur unique x, nous dressons la carte "la fonction qui applique une seule fonction (que nous nommons temporairement n) à la valeur x" sur la liste de toutes les fonctions.

2

La définition de la fonction:

applyAll = \fs -> \x -> map(\n -> n x) fs 

est le même que:

applyAll fs x = map(\n -> n x) fs 

Maintenant, vous pourriez demander: « Quels sont les -> s font là-bas si elles ne sont que des arguments à ma fonction applyAll.Haskell n'a pas de concept de fonctions multi-param. Ce que vous voyez comme des arguments multiples à une fonction est juste de nombreuses fonctions enchaînées ensemble chaque avec un seul argument. Dans le cas de applyAll, il est juste deux fonctions enchaînées ensemble:

(applyAll fs) -> x = map (\n -> n x) fs 

applyAll fs une seule fonction à un autre argument enchaîné identifié comme x pour obtenir une liste des valeurs renvoyées par map.

Je pourrais essayer dans ghci:

Prelude> :t applyAll 
applyAll :: [t -> b] -> t -> [b] 
Prelude> :t applyAll xs 

<interactive>:1:10: Not in scope: `xs' 
Prelude> let xs = [1..5] 
-- hah, BOOM! I told you haskell's strongly typed... 
Prelude> :t applyAll xs 

<interactive>:1:10: 
    Couldn't match expected type `t0 -> b0' with actual type `Integer' 
    Expected type: [t0 -> b0] 
     Actual type: [Integer] 
    In the first argument of `applyAll', namely `xs' 
    In the expression: applyAll xs 
Prelude> let xs = [(1 +), (2 +), (3 *), (4 /)] 
Prelude> :t xs 
xs :: [Double -> Double] 
Prelude> :t applyAll xs 
applyAll xs :: Double -> [Double] 
Prelude> :t applyAll 
applyAll :: [t -> b] -> t -> [b] 
Prelude> :t applyAll xs 3 
applyAll xs 3 :: [Double] 
Prelude> applyAll xs 3 
[4.0,5.0,9.0,1.3333333333333333] 

Quel est le type de map?

map :: (a -> b) -> [a] -> [b] 

Cela me dit que map prend une fonction - appelons-le f et une liste de valeurs pour revenir une autre liste de valeurs. La fonction f est une fonction qui prend une valeur de type a en renvoyant une autre de type b. Donc, map continue d'appliquer f à chaque valeur de la liste [a] pour renvoyer une autre liste remplie de valeurs de type b. Dans votre applyAll, la fonction f est \n -> n x. Il s'agit d'une expression lambda (que vous pouvez appeler une fonction anonyme) prenant une valeur identifiée par n et lui appliquant x. Cela se poursuit pour chaque élément de la liste d'entrée identifié par [a] dans la définition de type jusqu'à ce qu'il soit épuisé pour générer une autre liste identifiée par [b] dans la définition de type.

Questions connexes