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ë ?
Réponses
Trop de publicités?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 .
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)