
I've been digging through GHC source code to understand the reasons behind these behaviors. 1. There are use-cases of TemplateHaskell which do not want duplicate variables in patterns to be error. See a note in source code: https://gitlab.haskell.org/ghc/ghc/-/blob/d04a758296afdfd12300b0466967a42276... Quoting the linked note,
Consider this TH term construction: do { x1 <- TH.newName "x" -- newName :: String -> Q TH.Name ; x2 <- TH.newName "x" -- Builds a NameU ; x3 <- TH.newName "x"
; let x = mkName "x" -- mkName :: String -> TH.Name -- Builds a NameS
; return (LamE (..pattern [x1,x2]..) $ LamE (VarPat x3) $ ..tuple (x1,x2,x3,x)) }
It represents the term \[x1,x2]. \x3. (x1,x2,x3,x)
a) We don't want to complain about "x" being bound twice in the pattern [x1,x2] b) We don't want x3 to shadow the x1,x2 c) We *do* want 'x' (dynamically bound with mkName) to bind to the innermost binding of "x", namely x3. d) When pretty printing, we want to print a unique with x1,x2 etc, else they'll all print as "x" which isn't very helpful
To do this, a variable name has one of these two flavors:
"system" flavor for names generated by `newName`, and "normal" flavor for names
made by `mkName`. Duplicate variable name error is not checked for
"system" flavored
names.
Actually, using `mkName` works in an intended way (cause error)
ghci> (\x $(varP (mkName "x")) -> x) 1 2
<interactive>:10:3: error:
• Conflicting definitions for ‘x’
Bound at: <interactive>:10:3
<interactive>:10:7-23
• In a lambda abstraction
2. Quoting brackets ([| ... |], [p| ... |]) are translated to TemplateHaskell
code (in Q Monad) by desugarar. The desugarar
represents *every* bound variable name by names generated by
TH.newName. For example, the desugared code of [| \x y -> x y y |]
looks like below:
do { x <- newName "x"; y <- newName "y";
return $ (LamE [VarP x, VarP y] (...) ) }
And [p| x |] is translated in this manner too, causing the discussed behavior.
--
/* Koji Miyazato