DuplicateRecordFields and quasiquoters
GHC seems to parse record constructions/updates differently when DuplicateRecordFields
is in effect, and that seems to reflect in the data returned from expression quasiquotes:
data D = D { fld :: () }
[|D { fld = () }|]
-- without DuplicateRecordFields:
-- RecConE Main.D [(Main.fld, ConE GHC.Tuple.())]
-- with DuplicateRecordFields:
-- RecConE Main.D [(Main.$sel:fld:D, ConE GHC.Tuple.())]
[|d { fld = () }|]
-- without DuplicateRecordFields:
-- RecUpdE (UnboundVarE d) [(Main.fld, ConE GHC.Tuple.())]
-- with DuplicateRecordFields:
-- RecUpdE (UnboundVarE d) [(Main.$sel:fld:D, ConE GHC.Tuple.())]
Of interest is the selector Main.$sel:fld:D
. It has a name characteristic of GHC Core internal names. The quirkiness manifests in that we cannot lookupValueName "$sel:fld:D"
, and the renamer won't in general pick it up if we use Name (mkOccName "$sel:fld:D") NameS
or even Name (mkOccName "$sel:fld:D") $ NameQ $ mkModName "Main"
. Only Name (mkOccName "$sel:fld:D") $ NameG VarName (mkPkgName "main") (mkModName "Main")
will suffice (and that is the thing we receive from the expression quasiquoters above.
Another quirk is that when we try to reify that name we get back a declaration for a different identifier:
reify $ Name (mkOccName "$sel:fld:D") $ NameG VarName (mkPkgName "main") (mkModName "Main")
-- VarI Main.fld (AppT (AppT ArrowT (ConT Main.D)) (TupleT 0)) Nothing
Worth noting that if we do try to quasiquote an ambiguous update, we get a descriptive error message:
data D1 = D1 { fld :: () }
data D2 = D2 { fld :: () }
[|d { fld = () }|]
-- Ambiguous record updates not (yet) handled by Template Haskell
-- fld = ()
Question is, should TH know about such internal Core names at all and if so how should TH users tackle them.