Opérateur Haskell vs fonction priorité
j'essaie de vérifier quelque chose pour moi-même au sujet de l'opérateur et de la priorité de fonction dans Haskell. Par exemple, le code suivant
list = map foo $ xs
peut être réécrit comme
list = (map foo) $ (xs)
et finira par être
list = map foo xs
ma question était, pourquoi la première formulation ne serait pas réécrite comme
list = (map foo $) xs
puisque la priorité de la fonction est toujours plus élevée que la priorité de l'opérateur, mais je pense que j'ai trouvé la réponse: les opérateurs sont simplement pas autorisé à être des arguments de fonctions (sauf bien sûr, si vous les entourez de parenthèses). Est-ce exact? Si c'est le cas, je trouve étrange, qu'il n'y ait aucune mention de ce mécanicien/règle dans RWH ou apprendre vous un Haskell, ou l'un des autres endroits que j'ai cherché. Donc si vous connaissez un endroit, où la règle est indiqué, s'il vous plaît lien vers elle.
-- edit: Merci pour vos réponses rapides. Je pense que ma confusion est venue de penser qu'un opérateur littéral serait d'une certaine façon évaluer à quelque chose, qui pourrait être utilisée par une fonction comme argument. Cela m'a aidé à me rappeler, qu'un opérateur infix peut être mécaniquement traduit en fonctions préfixées. Faire cela à la première formulation donne
($) (map foo) (xs)
lorsqu'il n'y a aucun doute que ($) est la fonction de consommation, et puisque les deux formulations sont équivalentes, alors le $ littéral dans la première formulation ne peut pas être consommé par map.
5 réponses
Vous avez raison. Cette règle fait partie de la Haskell syntaxe définie par Rapport Haskell. En particulier, notez dans la Section 3, Expressions, que l'argument pour la fonction application (un fexp
) doit être un aexp
. Un aexp permet des opérateurs comme partie de sections, et aussi dans une expression entre parenthèses, mais pas des opérateurs nus.
map foo $ xs
, le Haskell syntaxe signifie que c'est analysée comme deux expressions qui sont appliquées à l'opérateur binaire $
. Comme le note sepp2k, la syntaxe (map foo $)
est une section de gauche et a un sens différent.
je dois avouer que je n'ai jamais beaucoup réfléchi à ce sujet et que j'ai dû vérifier dans le rapport pour voir pourquoi les opérateurs ont le comportement qu'ils ont.
premièrement, application (whitespace) est l'opérateur de priorité le plus élevé.
deuxièmement, dans Haskell, il n'y a vraiment pas de distinction entre les opérateurs et les fonctions, à part que les opérateurs sont infixés par défaut, alors que les fonctions ne le sont pas. Vous pouvez convertir des fonctions à infixer avec des backticks
2 `f` x
et convertir les opérateurs en préfixe avec parens:
(+) 2 3
Donc, votre question est un peu confus.
maintenant, fonctions et opérateurs spécifiques aura déclaré la priorité, que vous pouvez trouver dans GHCi avec "info":
Prelude> :info ($)
($) :: (a -> b) -> a -> b -- Defined in GHC.Base
infixr 0 $
class (Eq a, Show a) => Num a where
(+) :: a -> a -> a
infixl 6 +
montrant à la fois la préséance et l'associativité.
en plus des informations déjà fournies par d'autres réponses, notez que différents opérateurs peuvent avoir des précédents différents par rapport à d'autres opérateurs, en plus d'être Gauche-/Droite - ou non-associatif.
Vous pouvez trouver ces propriétés pour le Prelude
les opérateurs dans le Haskell 98 Rapport de la fixité de la section.
+--------+----------------------+-----------------------+-------------------+ | Prec- | Left associative | Non-associative | Right associative | | edence | operators | operators | operators | +--------+----------------------+-----------------------+-------------------+ | 9 | !! | | . | | 8 | | | ^, ^^, ** | | 7 | *, /, `div`, | | | | | `mod`, `rem`, `quot` | | | | 6 | +, - | | | | 5 | | | :, ++ | | 4 | | ==, /=, <, <=, >, >=, | | | | | `elem`, `notElem` | | | 3 | | | && | | 2 | | | || | | 1 | >>, >>= | | | | 0 | | | $, $!, `seq` | +--------+----------------------+-----------------------+-------------------+
tout opérateur qui n'a pas de déclaration de fixité est supposé être gauche associative avec priorité 9.
rappelez-vous, l'application de la fonction a la plus haute priorité (pensez à la priorité [1].
la différence est que les opérateurs infix sont placés entre leurs arguments, donc ceci
list = map foo $ xs
peut être réécrit sous forme de préfixe comme
list = ($) (map foo) xs
qui, par définition de l'opérateur$, est tout simplement
list = (map foo) xs
les opérateurs peuvent être passés en argument de fonction si vous les entourez de parenthèses (i.e. map foo ($) xs
, qui serait en effet passé comme (map foo ($)) xs
). Cependant si vous ne les entourez pas de parenthèses, vous avez raison qu'ils ne peuvent pas être passés en argument (ou assignés à des variables).
notez Aussi que la syntaxe (someValue $)
(où $
pourrait être n'importe quel opérateur) signifie en fait quelque chose de différent: c'est équivalent à \x -> someValue $ x
, c'est-à-dire qu'il applique partiellement l'opérateur à sa gauche opérande (qui dans le cas de $
est un noop bien sûr). De même ($ x)
applique partiellement l'opérateur à l'opérande de droite. Donc map ($ x) [f, g, h]
évaluer [f x, g x, h x]
.