Je sais intuitivement, il me semble que j'aiime dire,
1. $ retarder l'évaluation de la fonction à sa gauche
2. Évalue ce qui est à son droit
3. nourrit le résultat de sa gauche à sa droite. P> et cela me convient parfaitement lorsque, P> Ce que je ne comprends pas, c'est pourquoi , p> juger du type de $, n'est-ce pas que son (premier) argument devrait être une fonction? p> p>
3 Réponses :
Les sections vous permettent de fournir un argument à un opérateur binaire et de produire une fonction - une fonction qui attend l'argument restant. P>
Jetez un coup d'œil à http://www.hakell.org/hakellwiki/section_of_an_infix_opérator < / p> ($ [1..5]) code> est une section. C'est un opérateur partiellement appliqué. C'est un raccourci pour
(\ f -> f $ [1..5]) code>. P>
Votre question est vraiment sur ce que l'on appelle les sections de l'opérateur. Avec n'importe quel opérateur de haskell (je vais utiliser donc, le + code> comme exemple), vous pouvez écrire quelque chose comme
(+ arg) code> ou
(arg +) code>. Il s'agit juste de la syntaxe sténographie pour les fonctions anonymes
(\ x -> x + arg) code> et
(\ x -> arg + x) code>, respectivement. P>
($ [1..5]) code> syntaxe signifie simplement
(\ x -> x $ [1..5]) code> qui est le même comme
(\ x -> x [1..5]) code> (c.-à-d. une fonction qui passe
[1..5] code> à la fonction passée comme argument). p>
Ceci (\ x -> x $ [1..5]) efface vraiment ma confusion!
Cela a à voir avec l'analyse. Dans HASKELL, vous pouvez écrire c'est-à-dire, Essayons maintenant le même tour sur (op-arg) code> où
op code> est un opérateur d'infixe. Ce n'est pas la même chose que
((op) argone) code>. Et vous pouvez écrire
(arg op) code> aussi! Par exemple:
(+ 4) code> est la fonction
\ x -> x + 4 code> et
( 4 +) code> est la fonction
\ y -> 4 + y code>. En cas d'addition, celles-ci sont des fonctions égales, mais ce n'est pas vraiment important en ce moment. P>
$ code>: p>
Prelude> :t (($) length)
(($) length) :: [a] -> Int
Prelude> :t (($) [1,2,3,4])
<interactive>:1:6:
Couldn't match expected type `a0 -> b0' with actual type `[t0]'
In the first argument of `($)', namely `[1, 2, 3, 4]'
In the expression: (($) [1, 2, 3, 4])
Prelude> :t (length ($))
<interactive>:1:9:
Couldn't match expected type `[a0]'
with actual type `(a1 -> b0) -> a1 -> b0'
In the first argument of `length', namely `($)'
In the expression: (length ($))
Prelude> :t ([1,2,3,4] ($))
<interactive>:1:2:
The function `[1, 2, 3, 4]' is applied to one argument,
but its type `[t0]' has none
In the expression: ([1, 2, 3, 4] ($))
- code> peut avoir été un mauvais choix de l'exemple, car il s'agit de la seule et unique exception où
(op-arg) code> est pas i> représente une fonction.
En outre, ((-) 4) code> et
(4 -) code> sont la même fonction,
(\ x -> 4 - x) code>.
Cela signifie-t-il parce que (-) est laissé associé, à la fois ((-) 4) et (4 -) moyens (\ x -> 4 - x), tandis que ($) est juste associé, à la fois ($ Func) et ($ arg) signifie (\ x -> bar $ a) où a signifie fonction de func ou argers?
Oups, laissez-moi résoudre ça. Merci, Scott.
Cela n'a rien à voir avec l'associativité. La chose qui est confuse @Znatz est que f $ Longueur code> est logique si
f code> a le type correct. Ainsi, Haskell est analysant
$ Longueur code> comme
\ f -> FT $ Longueur code>, comme
$ [1,2,3,4] code> est analysé comme
\ f -> f $ [1,2,3,4] code>.
OK je vois. ($ de longueur) ((* 2).) [1..10] code> me donne un
20 code> attendu. Cependant, il est toujours très confus que
((-) 4) code> est analysé comme
(\ x -> 4 - x) code> mais pas
(\ x -> x - 4) code>
C'est parce que ((-) 4) code> n'est pas une section de l'opérateur du tout. C'est juste une application partielle normale de
- code>, et il reçoit ses arguments à gauche ou droite comme toutes les autres fonctions. Comme il faut d'abord son argument gauche, vous obtenez
(\ x -> 4 - x) code>.
Ce n'est pas sur
($) code>, mais sur les sections de l'opérateur.
$ code> Ne pas i> L'évaluation de la fonction est laissée. Vous pouvez le confondre avec
$! Code>, qui force une évaluation partielle de l'argument à son droit avant de l'aligner sur la fonction à sa gauche.
C'est la syntaxe de "section" au travail. haskell.org/onlinereport/hakell2010/...
Et quant à ce que c'est bon pour: Vous pouvez l'utiliser lorsque vous souhaitez appliquer une liste de fonctions à une valeur:
carte ($ [1..5]) [longueur, somme, produit] code> .
@ dave4420
id $! x == x `SEQ` id x code> ne force rien, ni donc on m'a dit.
@Willness Eh bien,
SEQ code> ou
($!) Code> ne sont évalués que lorsque leur résultat est demandé. Depuis l'argument et le résultat de
ID code> sont les mêmes,
id $! x code> force l'évaluation de l'argument,
x code>, (à une forme de tête faible) exactement lorsque le résultat,
x code>, doit être évalué (à WHNF) . Il est donc difficile de déterminer si le
($!) Code> a fait quelque chose là-bas. Mais dans une implémentation où
a `SEQ` B code> évalue
a code> avant
b code> (qui n'est pas requis par la sémantique de
SEQ Code>), Si vous avez l'air assez difficile, vous pouvez voir que
id $! indéfini code> Erreurs avant
ID code> retourne. Pétortisme inutile>
@Danielfischer La raison pour laquelle je m'attardais, c'est que j'étais confus par cela assez à quelques reprises en supposant que
$! Code> "force son argument". La vraie question, quand? I>, est laissée de côté par cette déclaration magique. Serait-il préférable de dire que
$! Code> "arrange pour que son argument soit forcé avant d'être envoyé à la fonction, lorsque le résultat de la demande de fonction est forcé"?
@Will confusion commune. Je n'ai bien sûr jamais souffert ( siffle innocemment i>). La réponse est une fonction ne peut rien faire - en particulier, ne pas forcer l'évaluation de l'un de ses arguments - avant qu'elle ne soit appelée. Quand est-il appelé? Lorsque son résultat doit être évalué, non plus tôt, pas plus tard. En ce qui concerne votre édition, oui, il serait probablement préférable de dire
($!) Code> force son deuxième argument lorsque son résultat est nécessaire pour être évalué.