[Template-haskell] Defining a function and using it in a splice within the same module

Alfonso Acosta alfonso.acosta at gmail.com
Wed Oct 24 09:49:54 EDT 2007


On 10/24/07, Simon Peyton-Jones <simonpj at microsoft.com> wrote:
>
> | "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.


More information about the template-haskell mailing list