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.

35
demandé sur Boris 2010-06-27 00:24:39

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.

24
répondu John L 2010-06-26 21:56:38

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é.

32
répondu Don Stewart 2013-05-16 08:58:01

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].

12
répondu mucaho 2015-06-04 17:28:27

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
11
répondu Paul Kuliniewicz 2010-06-26 20:33:39

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].

9
répondu sepp2k 2010-06-26 20:29:42