32 votes

Pourquoi faut-il un $ dans les appels du type "runSomeMonad $ do ..." ?

Apparemment, la seule interprétation possible de runSomeMonad do ... es runSomeMonad (do ...) . Pourquoi la première variante n'est-elle pas autorisée par la syntaxe Haskell ? Existe-t-il un cas où foo do bar pourrait être ambiguë ?

26voto

Jon Purdy Points 19408

Notez que vous pouvez observer cet effet avec non seulement do mais aussi let , if , \ , case , les extensions mdo y proc et le redoutable unaire - . Je ne vois pas de cas où cette disposition serait ambiguë sauf pour les unaires - . Voici comment la grammaire est définie dans le fichier Rapport 2010 sur le langage Haskell, §3 : Expressions .

exp
    → infixexp :: [context =>] type
    | infixexp

infixexp
    → lexp qop infixexp
    | - infixexp
    | lexp

lexp
    → \ apat1 … apatn -> exp
    | let decls in exp
    | if exp [;] then exp [;] else exp
    | case exp of { alts }
    | do { stmts }
    | fexp

fexp
    → [fexp] aexp

aexp
    → ( exp )
    | …

Il se trouve qu'il n'y a pas de cas défini dans fexp (application de fonction) ou aexp (expression littérale) qui permet à une personne non paraphrasée lexp (lambda, let etc.) Je considère qu'il s'agit d'un bogue dans la grammaire.

En corrigeant ce problème, il n'est plus nécessaire d'avoir des les $ hacking dactylographique .

-2voto

Yghor Kerscher Points 27

Par défaut, les fonctions sont regroupées comme suit :

(f g h x)

C'est-à-dire regroupés "à gauche", avec g , h y x en tant qu'arguments pour f . Au lieu de cela, ce que vous imaginez :

(f (g (h x)))

Ils seraient regroupés "à droite". ($) est simplement l'opérateur qui vous permet d'effectuer un regroupement d'applications de fonctions "vers la droite" :

ghci> :i ($)
($) :: (a -> b) -> a -> b   -- Defined in `GHC.Base'
infixr 0 $

Ce qu'il faut faire infixr 0 vous dit que $ peut être utilisé entre les arguments ( infixe r) et il le fait en regroupant "à droite" (infixe r ).

Et le 0 est simplement la priorité de l'opérateur, ce qui signifie que si une autre fonction apparaît à côté de ($) il se liera plus fortement que lui. Dans les cas où vous devez faire une application de fonction mais que vous avez besoin d'une plus grande priorité, vous devez utiliser (.) :

ghci> :i (.)
(.) :: (b -> c) -> (a -> b) -> a -> c   -- Defined in `GHC.Base'
infixr 9 .

Consultez également un article à ce sujet à l'adresse suivante FP Complet . (Je n'en suis pas l'auteur ; je pense simplement qu'il s'agit d'une excellente explication)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X