
Dear Cafe, what is the reasoning behind the behavior of the following two Haskell expressions: ghci> :set -XTemplateHaskell ghci> let f x ($([p| x |])) = x in f 1 2 2 ghci> let f ($([p| x |])) x = x in f 1 2 2 I'd have guessed that they should both fail compilation with "Conflicting definitions for ‘x’" like the following expression. ghci> let f x x = x in f 1 2 error: ... Moreover, it seems odd that the "x" on the right side always refers to the rightmost pattern variable "x" (regardless if quoted or not). Cheers, Kai

On Tue, Apr 27, 2021 at 04:06:27PM +0200, Kai-Oliver Prott wrote:
Moreover, it seems odd that the "x" on the right side always refers to the rightmost pattern variable "x" (regardless if quoted or not).
I guess this comes from the translation f x x = <rhs> -> f = \x -> \x -> <rhs> I'm not familiar enough with TH to say whether one should expect a warning though. Tom

I have tried the examples as well and, indeed, I get a shadowing warning for the first example (along with an unused warning). ghci> :set -XTemplateHaskell -Wall ghci> let f x $([p| x |]) = x in f 1 2 warning: This binding for 'x' shadows... warning: Defined but not used: 'x' However, for the second example I only get the unused warning. ghci> let f $([p| x |]) x = x in f 1 2 warning: Defined but not used: 'x' This still seems to be a bit inconsistent (not mentioning that I would also expect both examples to fail because of non-linear occurrences of 'x'). Cheers, Finn On 27/04/2021 16:28, Tom Ellis wrote:
On Tue, Apr 27, 2021 at 04:06:27PM +0200, Kai-Oliver Prott wrote:
Moreover, it seems odd that the "x" on the right side always refers to the rightmost pattern variable "x" (regardless if quoted or not).
I guess this comes from the translation
f x x = <rhs>
->
f = \x -> \x -> <rhs>
I'm not familiar enough with TH to say whether one should expect a warning though.
Tom _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

I have tried too, and can provide a few points to raise. See the following gist:
https://gist.github.com/viercc/9d22ea0c740183ba0e4b5b00d654dcd3
* This happens with "normal" non-interactive compilation by GHC
* Confirmed with both GHC 8.10.4 and GHC 9.0.1
* This happens with duplicate definitions in let
let {x = 1; $([p| x |] :: PatQ) = 2 } in x
* There's another inconsistent behavior with pattern splices
nested inside another quote
\x $([p| x |] :: PatQ) -> x -- compiles to \_ x -> x
[| \x $([p| x |] :: PatQ) -> x |] -- compiles to [| \x x1 -> x |]
--
/* Koji Miyazato

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

If you think there's a bug, you may want to file a GHC ticket about this, and include the results of your digging:
https://gitlab.haskell.org/ghc/ghc/-/issues
Thanks,
Simon
| -----Original Message-----
| From: Haskell-Cafe
participants (5)
-
Finn Teegen
-
Kai-Oliver Prott
-
Simon Peyton Jones
-
Tom Ellis
-
宮里洸司