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 <viercc@gmail.com> */