Closed odr closed 6 years ago
Is it possible to use qualified names (
F.FooSym0
,F.sFoo
) for qualified name in template?
Unfortunately, no. Template Haskell doesn't give you any way to distinguish between a qualified and non-qualified name, as the following program demonstrates:
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
import qualified Prelude
import Prelude
main :: IO ()
main = putStr
$(do ConT nonQualName <- [t| Bool |]
ConT qualName <- [t| Prelude.Bool |]
stringE $ unlines
[ "Non-qualified name " ++ show nonQualName
, "Qualified name " ++ show qualName
, "Are they equal? " ++ show (nonQualName == qualName)
])
λ> main
Non-qualified name GHC.Types.Bool
Qualified name GHC.Types.Bool
Are they equal? True
Therefore, singletons
can't generate F.FooSym0
or F.sFoo
, as it has no way to know that the original F.foo
name was qualified to begin with.
I can't recall if there's an open GHC ticket about this, but one thing is for sure: this is not possible unless Template Haskell were to be changed so that qualified names would be preserved when quoted.
Thank you for explanation. I think it could be done with new QuasiQuoter (say, [dq| ... |]). Am I right? Though I am not too much interested in it.
I think it could be done with new QuasiQuoter (say, [dq| ... |]). Am I right?
I don't think it would even be possible with quasiquoting. You'd still have to deal with names like F.foo
, where F
is some qualified prefix. The Template Haskell API for names only gives you NameG
and NameQ
for dealing with qualified names, but they require giving a full module name, not just a prefix. For instance, if you had import Prelude as Prel
, then you'd need to be able to figure out that Prel.show
actually means NameG "base" "Prelude" "show"
, which is a very non-trivial task (especially since Template Haskell doesn't give you the Prel
prefix in the first place).
Hmm... Maybe it could be done more simple then with QQ?
[d| bar =F.foo|]
is something like
[ValD (VarP bar_1) (NormalB (VarE ModuleFoo.foo)) []]
We have to generate other definitions with changing e.g. ModuleFoo.foo
to ModuleFoo.sFoo
.
Isn't it how it works now? I suppose that now Singletons use just "local" name sFoo
, no?
I assume that if we import ModuleFoo qualified it is accessible from TH with its full name (i.e. it doesn't depend on qualified name). It looks natural to me but probably I am too optimistic... I didn't check all these stuffs.
It is true that quoted names do give you the module information, yes. However, this is often not enough to figure out where the singleton definitions are!
For instance, if you quote [| id |]
, then you'll get a Name
that's (roughly) NameG "base" "Prelude" "id"
. However, the corresponding singleton definitions for id
are not in the Prelude
—they're in singletons
, a completely different package! You'd have the same problem in your scenario, since you cannot know in general whether the singleton definitions for F.foo
were defined in the same module that F
refers to or not.
In short, this is a complicated problem that's further complicated by Template Haskell inadequacies, and I don't see a straightforward solution.
I agree with Ryan's summary above. Even if TH could track such qualifications, making use of them would require the assumption that singleton definitions are in the same module as the original definitions. This is not true all the time. I suppose you could also teach singletons
a mapping from qualified original names to the modules where the singletons are defined, but that seems overwrought, to me.
My bottom line: singletons
does unhygienic, unpleasant things with names. This means that we're never going to be handle all naming situations gracefully. And I don't see a better way while still allowing users to access singletons
names without yet more TH.
I'll opt to close this, as we can't fix this on singletons
's end cleanly. I'll note that there are really two problems here:
F.foo
, where F
is a qualified prefix.singletons
does not grant users the power to change what names are generated if the default scheme isn't to their liking.The second issue is surmountable if we fixed #204. The first issue, on the other hand, would need to be fixed by adding more functionality to Template Haskell. So perhaps fixing that could be a jumping point into getting back to this issue.
If I define in one module
and import it qualified (as
F
) to another module and useF.foo
in another template:I get errors like
Not in scope: type constructor or class ‘FooSym0’
If I importFooSym0
unqualified I also get an errorVariable not in scope: sFoo
Is it possible to use qualified names (
F.FooSym0
,F.sFoo
) for qualified name in template?