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@HotPOP.com