On 10/24/07, Simon Peyton-Jones
| "You can only run a function at compile time if it is imported from | another module. That is, you can't define a function in a module, and | call it from within a splice in the same module." | | Unfortunately I have encountered this problem more times than I'd like | while using TH to implement a DSL. My usual solution is to generate a | function to process the extra arguments which cannot be passed to the | splice (i.e. push the arguments out of the splice so that I can use | functions defined in the same module).
I don't quite understand your workaround. Can you describe it a bit more?
Well, it doesn't solve the issue of executing things at compile-time, it simply delays their execution until proper runtime. As a (simplified) example, in my System Modelling DSL I have to create system definition. That is done by providing the function Name together with the identifiers of its inputs and outputs. inputs = ["in1", "in2"] outputs = ["out1", "out2"] f :: Signal Int -> Signal Int -> (Signal Int, Signal Int) f = ... Since it is not possible to do system :: SysDef system = $(mkSysDef 'f inputs outputs) due to the limitation we mentioned I simply do system = $(mkSysDef 'f) inputs outputs where mkSysDef :: Name -> [String] -> [String] -> SysDef My solution does not solve the problem. It rather bypasses it. Furthermore, mkSysDef unfortunately cannot do static checking (for example, it cannot make sure that all the inputs and outputs have different identifiers). However, that's better than asking the user to create the system definitions and identifiers in different modules.
A possible approximation is: see if *anything* defined in this module is called from within a splice, and if so compile *everything* to bytecode, just in case.
Excuse my ignorance (I'm not familiar with the internals of GHC) but, wouldn't it be possible to compute a dependency graph for each splice before executing them? Based on that, the compiler could decide whether to generate bytecode for a function or not.
If there is more to add (e.g. details of your workaround), add commments to that ticket so we accumulate the lore in one place.
Since what I propossed is more "bypassing the problem" than a workaround I don't know if its significant for the ticket.