I am not very versed in the Haskell pattern, but based on my limited understanding, the problem is that three in a sense āstill definedā when the GHC tries to compile $(findx three) , while all components from $(findx (Alpha "Four" 4)) already fully defined.
The main problem is that all definitions in one module affect each other's value . This is due to the type of output, as well as to mutual recursion. The definition of x = [] can mean many different things, depending on the context; it could be binding x to an Int list or an IO () list, or something else. The GHC may need to process the entire module to find out what exactly it means (or that this is actually an error).
The code that Template Haskell emits into the module that compiles should be considered by this analysis. Thus, this means that the Haskell template code must be executed before the GHC finds out what the definitions in the module mean, and therefore logically you cannot use them.
Things that were imported from other OTOH modules were already fully verified when the GHC compiled this module. There is no more information that needs to be learned about them by compiling this module. Thus, they can be accessed and used before compiling the code in this module.
Another way to think: maybe three should not really be Alpha type. Perhaps it was a typo, and the constructor should have been Alphz . Typically, the GHC learns about these types of errors by compiling all other code in a module that uses three to find out if it is inconsistent or not. But what if this code uses or is used by things that emit only $(findx three) ? We donāt even know which code will work until we run it, but we cannot decide whether three printed correctly until we run it.
Of course, this restriction could be slightly reduced in some cases (I donāt know if it would be easy or practical). Perhaps we could get the GHC to believe that something is ādefined earlierā if it is imported, or if it uses only other things that are ādefined earlierā (and possibly has an explicit type signature). Perhaps he can try to compile the module without running the TH code, and if he succeeds in completely executing typecheck three before he encounters any errors, he can pass this into the TH code and then recompile everything. The downside (besides working) would be much harder to specify which exact restrictions apply to what you can pass to the Haskell template.
Ben
source share