[Template-haskell] program transformation

Simon Peyton-Jones simonpj at microsoft.com
Thu Oct 30 15:28:39 EST 2003


I'm returning to the question of reification in Template Haskell.  

Would it help here if one could say

	reify :: Var -> Q Decl

and get the declaration for 'reverse'?  (Var is as in the "notes"
Postscript file I posted yesterday.)

I can arrange that iff reverse is defined in the same module.  Thus

	reverse = ...
	foo = $( do { rev_dec <- reify 'reverse; ... })

(The 'reverse is like a quote [|reverse|], but gets a Var not an Exp.)


This is much harder if reverse is imported, because we simply don't have
access to reverse's source code any more.  (But type constructors and
classes are fine. -- excluding the default-method bindings of the
class.)

Would this help?

Simon


| -----Original Message-----
| From: template-haskell-bounces at haskell.org
[mailto:template-haskell-bounces at haskell.org] On
| Behalf Of Ganesh Sittampalam
| Sent: 12 September 2003 17:10
| To: template-haskell at haskell.org
| Subject: [Template-haskell] program transformation
| 
| I'm currently investigating the possibility of redoing MAG in Template
| Haskell. MAG is essentially (at least for the purposes of this email)
a
| system that takes a source program and a bunch of rewrite rules, and
| applies the rewrite rules to the program.
| 
| I'd like to be able to do this in TH with as little syntactic noise
for
| the user as possible. The general idea (at the moment) would be to put
the
| original program within [d| |] brackets, the set of rewrite rules
within
| [| |] brackets, run a function on the two and splice in the result.
| 
| It's not the main purpose of this email, but I should mention that
being
| able to splice in code in the same module as it is defined would be
very
| useful for this application, since otherwise any module that makes use
of
| this will need to be split into two.
| 
| There was a previous discussion about TH and Hydra at
|
http://www.haskell.org/pipermail/template-haskell/2003-January/000008.ht
ml,
| which ended up with the idea of using [d| |] brackets for code that
was to
| be transformed. The extra twist for me is that I have this set of
rewrite
| rules that I also want to use quasi-quotes for.
| 
| A simplified example of a rewrite rule that uses the associativity of
(++)
| is as follows:
| 
| \xs ys zs -> (xs ++ ys) ++ zs ==> xs ++ (ys ++ zs)
| 
| ==> is an operator of type a -> a -> RewriteRule, so GHC will check
for me
| that the rewrite rule is type correct. The lambda binding for xs, ys
and
| zs specifies that the rewrite rule works for any value of them, and
also
| keeps the compiler happy that I haven't used undefined variables. Of
| course, I'm never intending to actually run this code, I'll just use
the
| result of quasi-quoting it to apply transformations.
| 
| Anyway, this all works fine. Now, let's suppose that my original
program
| defines the function reverse (hiding the Prelude reverse function),
and I
| want to write a rewrite rule mentioning reverse too. I end up with
| something like this:
| 
| reversecode =
|  [d|
|      reverse [] = []
|      reverse (x:xs) = reverse xs ++ [x]
|  |]
| 
| rules = [| [ reverse [] ==> [] ] |]
| 
| The second definition won't compile, since reverse isn't in scope
| anywhere. I'm trying to work out a good solution to this problem; so
far
| I've come up with the following ideas:
| 
| (a) Merge the rewrite rules and the declarations. E.g:
|     [|
|      let reverse [] = []
|          reverse (x:xs) = reverse xs ++ [x]
|      in [ reverse [] ==> []
|           ...
|         ]
|     |]
|   Pros: - this should actually work for me right now (not actually
tested
|         - though)
|   Cons: - it violates the nice separation between code and
transformation,
|         - it doesn't read nicely for the user; in particular it'll be
|           unpleasant for them to take some existing code and decide to
use
|           MAG on it
| 
| (b) Use a lambda-abstraction or let-binding to make "reverse" appear
to be
| defined.
|   Pros: - again this ought to work right now
|   Cons: - unless I textually duplicate code, it won't be properly
type-checked
|         - the renamer will rename "reverse" and I'll have to make some
|           nasty assumptions about how that works to get back to the
|           original form
| 
| (c) Turn the rewrite rules into a separate [d| |] block, and splice in
| $(reversecode) at the beginning
|   Pros: - Not nearly as inelegant/nasty as (a) or (b)
|   Cons: - I still have to search the declaration list for the rewrite
|           rules
|         - This will fall foul of the (second) bug I reported yesterday
| 
| (d) Say something like let $(reversecode) in reverse [] ==> []
|   Pros: - Seems even less nasty than the above options
|   Cons: - disallowed by design in TH, for good reasons; it destroys
the
|           ability to see where things are bound statically
| 
| I'd appreciate any comments or alternative suggestions. Ideally I
think
| I'm looking for some nice concise way to say that the rewrite rules
| quasi-quotes should be parsed and type-checked in the context of the
| declarations in original code quasi-quotes.
| 
| Cheers,
| 
| Ganesh
| 
| 
| 
| _______________________________________________
| template-haskell mailing list
| template-haskell at haskell.org
| http://www.haskell.org/mailman/listinfo/template-haskell




More information about the template-haskell mailing list