[Template-haskell] quasi quotes and Q monad
Bulat Ziganshin
bulatz at HotPOP.com
Wed Jan 4 11:51:16 EST 2006
Hello Ch.,
Tuesday, January 03, 2006, 6:13:53 PM, you wrote:
>>i feel that it will be clearer if you will compare Q with IO monad
>>
CAH> the comparison doesn't work with the IO monad because the user runs the
CAH> Q monad every time when splicing a generated expression.
imvho, you don't "feel" the Q monad properly. you cannot splice
expression in arbitrary place because there is no runST equivalent for
Q monad
in more detailed view, all state monads, including ST, IO and Q is a
way to DECLARE sequence of some operations having side effects. in ST
monad, thos side effects affects state s, which is a parameter of
monad. afaik, as you pass this state explicitly between operations,
you can turn monadic code in pure functional one
in the IO monad, state modified is RealWorld. The only way to get it
is from main function. Functions with type "... -> IO a" is the only
functions which receives RealWorld as one of its arguments and then
returns modified RealWorld. Because of it, IO monad can't be escaped,
in other words - non-IO fucntion just don't receive and don't return
RealWorld, so it can't modify it in any way and can't execute IO
actions, which need this parameter. This ceremony of
receiving/returning RealWorld just used to "burn" action to some
place in the sequence of IO actions, called by the `main`. and having
place in that sequence is the only way to ensure that some action will
be really executed. so, RealWorld is just an artifical state, used to
sequence actions and link them to `main`
Q monad is the way to sequence all name-generation operations. that is
a global task, so all actions in Q monad must be "linked" to some
top-level splice to be really executed. all top-level splices are
executed sequentially like statements in `do` action and
name-generator state are passed between these calls, as Tomasz
mentioned
unless you use runQ (and it's a very bad practice), you cannot escape
Q monad, and it's fair - you must inform TH about order in which you
want to generate names, and "burning" all your Q actions to some place
in the global sequence (i.e. execute them in some top-level splice
sequence) is the method of archiving that
CAH> In contrast, the user can't run the IO monad out of a functional non-monadic
CAH> expression, except when making use of unsafe features.
CAH> Concerning the ST monad (for simplicity, consider one defined by the user
CAH> without local type quantification) it is possible, in principle, to join
CAH> the states of
CAH> two ST runs overlapping in time, if you have a concept of what you would
CAH> like to
CAH> achieve, may depend on the application.
CAH> Tomasz mentioned an important point: the monad laws for return. As long as
CAH> they are respected by the quasi quote implementation, a return cannot
CAH> destroy
CAH> monadic information in the scope where the splice is inserted, so it is
CAH> safe to
CAH> turn an Exp into a (Q Exp) just be using return. How to generate the names
CAH> inside this Exp is the job of the user, at the point where the spliced
CAH> expression
CAH> was created there should be a Q monad available with an appropriate
CAH> name generation history. As long as the expression to be spliced is
CAH> taken from the same
CAH> scope, and this is the case in simple examples, there is no problem
CAH> because the expression
CAH> need not be passed as a parameter but can just be cited, even across
CAH> quotation brackets
CAH> due to cross-stage persistence.
i feel that we both right :) yes, the Q monad is like ST in that it
carries explicit state - number of last generated name. and yes, Q is
like IO in what it's "one-for-all" and cannot be escaped, i.e.
executed independent of main sequence :)
--
Best regards,
Bulat mailto:bulatz at HotPOP.com
More information about the template-haskell
mailing list