Proposal: Overloaded Quotes for Template Haskell
Simon PeytonJones
simonpj at microsoft.com
Thu Jan 5 19:08:36 CET 2012
I'm sorry Michael, I just don't get it. Maybe I'm just being slow.
One difficulty is that toplevel splices (and hence, recursively) nested splices, must be run in the typechecker monad; and TH knows nothing of that monad. That's why the Quasi class exists in the first place; it says exactly what the "host monad" (the typehcecker in this case) must support. By moving to ST you are fixing the monad, and I just don't see how to make that work.
Perhaps the thing to do is to write some typing judgements, as in the TH paper, or to implement a prototype, or to write up a design in more detail. Template Haskell always does my head in.
Sorry not to be more helpful
Simon
 Original Message
 From: Michael D. Adams [mailto:mdmkolbe at gmail.com]
 Sent: 31 December 2011 19:59
 To: Simon PeytonJones
 Cc: libraries at haskell.org
 Subject: Re: Proposal: Overloaded Quotes for Template Haskell

 On Sat, Dec 31, 2011 at 7:55 AM, Simon PeytonJones
 <simonpj at microsoft.com> wrote:
 >  > And indeed there is such a function: it's called runQ.
 >  >
 >  > So I think what you want is already available.
 > 
 >  If there are no splices in the quote then, yes, that is sufficient.
 >  However, as there is no function of type "forall m. Quasi m => m Exp
 >  > Q Exp", the contents of all splices must be of type "Q Exp". Thus
 >  in the expression "[ ... $( foo ) ... ]" there is no way for foo to
 >  modify the state of the memoization table.
 >
 > I'm sorry, I don't understand what you say here.
 >
 > You started your post by saying that you want quote to be of type
 > forall m. Quasi m => m Exp
 > But they already are! (With a newtype wrapper.)

 The constructor of that newtype wrapper is *not* exported by the
 Template Haskell libraries. The destructor *is* exported in the form
 of "runQ" (which is equivalent to "unQ" (and I don't know why the two
 names)), but the constructor "Q" is not.

 However, while it may look like exporting "Q" is sufficient to get
 what I want, that doesn't quite work.

 To see why it doesn't work, suppose we have:
  "c :: StateT S Q Exp > StateT S Q Exp" and
  "e :: StateT S Q Exp" and
  "instance Quasi (StateT s Q)".

 Now, consider "c (runQ [ ... $(Q (e)) ... ])". There will be a type
 error in the application of "Q" to "e" since "forall m. Quasi m => m
 Exp" is not an instantiation of "State S Q Exp".

 However, if the types of quotes and splices are generalized as I
 proposed, then "c [ ... $(e) ... ]" will type check just fine and
 achieve the effect that I'm after.

 Another way to think of this distinction is to the quotes as
 functions. The function "\e = [ ... $e ... ]" has type "Q Exp > Q
 Exp". On the other hand the function "\e > runQ [ ... $(Q e) ...
 ]" has type "(forall m. Quasi m => m Exp) > (forall m. Quasi m => m
 Exp)". Note that the two "m" do not unify. Under my proposal "\e >
 [ ... $e ... ]" would have type "forall m. Quasi m => m Exp > m
 Exp".
More information about the Libraries
mailing list