Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate dynamic Name in template haskell using the current scope

I'm writing a template haskell splice, and am struggling to generate the right kind of Names. If I want to generate a known name (say, a function f), I can use 'f. This requires f to be in scope where I'm defining the splice, not where it's used, which is exactly what I want.

Now I want the same thing, but for a dynamic name. For example, say my splice takes an n :: Int as an argument. I want to generate "f" ++ show n as a Name, looked up at the splice definition site, not the use site.

I've tried a couple of options: mkName and lookupValueName both require the name to be in scope at the use site. The single quote syntax needs a literal name, not a dynamic one.

Finally I started experimenting with mkNameG. Since the functions come from the same package as I'm using them in, I started with the package name, but that gave errors Can't find interface-file declaration for variable the-package-name:Some.Module.f0. After some source reading I found places where the package name "main" was used. That seems to work in GHCi, but when compiling I still get the same error.

Is there any way to do this? I could enumerate all the options of course, but I'd like to avoid that, since the whole point of this exercise is to make the code more dynamic.

like image 632
Erik Hesselink Avatar asked May 18 '16 14:05

Erik Hesselink


1 Answers

I imagine you can do this by extracting the package name from a particular Name 'f0, then passing it to mkNameG_v. This might not be a good idea for two reasons:

  • Writing 'f checks that the identifier f really is in scope, whereas you can pass anything to mkNameG and not get an error until you try to use the Name in some way. You'll have to ensure in some other way that you only build Names for identifiers that actually exist, or recover from the error when you use the Name (unless you just want to let GHC fail with the error you saw).

  • Writing 'f also counts as a use of f. Unused unexported definitions are simply discarded, so you will not be able to refer to them with mkNameG. You will have to find some other way to ensure that your "f" ++ show n identifiers are used.

like image 123
Reid Barton Avatar answered Oct 24 '22 05:10

Reid Barton