3

In Template Haskell, the Q monad is where all the magic happens. However, Q has a pretty limited API. I would like to have a value of type valueNameStore :: Q (String -> Maybe Name) which basically captures the functionality lookupValueName :: String -> Q (Maybe Name) but with the store of variables available at the moment it is bound.

I think this is theoretically sound: I shouldn't need to sequence my lookups if I am performing them with respect to a shared constant state that is a snapshot of the state of Q when I initially called bind on valueNameStore.


If this isn't possible, is there any way of forcing it through in an unsafe way? I am willing to lower myself to whatever hacks involving unsafePerformIO...

Alec
  • 31,829
  • 7
  • 67
  • 114

1 Answers1

0

The answer is basically no. There might be some unreasonable way to do this if you can enumerate the names in scope somehow. While you're correct that an operation with the type and semantics you suggest is perfectly sensible, that doesn't mean it's (reasonably) implementable from the provided interface even with unsafePerformIO.

Basically, the mapping from strings to Names is mutable. What you want to do requires taking a snapshot of that mutable dictionary. The API doesn't provide such functionality and as far as I can tell it also doesn't provide you with the tools to manually copy the data out yourself. Attempting to use unsafePerformIO will just cause you to get whatever bindings are in the mapping at the time the expression is evaluated, which, if you've changed scope, will be different than the ones when you called the Q action.

Derek Elkins left SE
  • 2,079
  • 12
  • 14
  • What if I _was_ willing to get whatever mappings are in the mapping at the time the expression is evaluated? I don't see how `unsafePerformIO` would help. Yeah, the snapshot idea is what I thought, but... a lot of stuff is in scope. Even just the Prelude... – Alec Mar 23 '17 at 07:09
  • Again, `unsafePerformIO` doesn't help here. `lookupValueName` lives in the `Q` monad and most operations (namely all the lookup ones) can't escape the `Q` monad. – Alec Mar 23 '17 at 07:44
  • No offence intended, but are you even trying the things you are suggesting? The `IO` instance of `Quasi` [doesn't permit any lookups](http://hackage.haskell.org/package/template-haskell-2.11.1.0/docs/src/Language.Haskell.TH.Syntax.html#line-124). `runQ` won't help - you actually cannot (AFAIK) escape `Q`. – Alec Mar 23 '17 at 07:53