(oops. Sorry about the double-post. Sent it with a wrong From: line and it doesn't seem to have come through...) Hello all, Long story, but one thing after another led me to resort to TH as a means to (re-)implement Conor McBride's (applicative) idiom brackets[0], where: [[ g x0 x1 ... xn ]] expands to pure g <*> x0 <*> x1 <*> ... <*> xn (pure and <*> come from Control.Applicative.) While I can't use [[ and ]], I can define a CPP macro: #define II(e) $( idiom [| e |] ) where the idiom function does the above rewriting at compile time. II( ... ) looks acceptable as a replacement for [[ ... ]]. Good. (Just as well, since the type-level implementation of the iI Ii brackets given in [1] will no longer work as of GHC 6.5, but is used fairly extensively in the Epigram 2 source code...) Even though (g x0 x1 ... xn) won't typecheck outside of a quotation, I can nevertheless get away with [| g x0 x1 ... xn |] because it is /internally/ consistent. (Template Meta-programming for Haskell, ยง7.1 paragraph 3; figure 2, rule BRACKET.) Yesterday, Conor pointed out that the if and case constructs are pure 'things', and since my implementation of the above idiom function seemed capable of this sort of syntax mangling, why not treat them as one more case in the applicative/monadic idiom bracket. (I've always wanted monadic if and case expressions. Hurrah!) The idea being that: II( if c then t else e ) and II( case d of { ... } ) would expand to c >>= \ b -> if b then t else e and d >>= \ x -> case x of { ... } respectively. I'd already written some of this up, and just got around to implementing the changes earlier tonight, but I'm stumped by the internal type consistency restriction: c has type (Monad m => m Bool), which means [| if c then t else e |] isn't 'internally consistent'. With the case-expression, d has type (Monad m => m a); (x :: a); and the elided patterns in { ... } match values of type a. So [| case d of { ... } |] won't get past the supposed 'sanity check'[2] either. :( My current want-it-now 'solution' is to comment out the sole tcSimplifyBracket invocation in ghc/compiler/typecheck/TcSplice.lhs. Clearly this is the wrong approach, seeing as other people would like to use this too. (I presume this will do what I want. I'm still waiting for stage1 to finish building...) I guess a more constructive approach would be to hack in an alternative unchecked quotation bracket, [s| ... |] say ('s' stands for 'syntax'). If upstream is willing to consider such an extension, I'll get started... Any alternative suggestions before I do? :-/ Thanks for listening, /Liyang [0] http://cs.nott.ac.uk/~ctm/IdiomLite.pdf [1] http://cs.nott.ac.uk/~ctm/Idiom.pdf [2] I am sane, right? I mean, is there any other reason for the internal type-consistency check other than to detect /potential/ errors /earlier/?
Hi Liyang, On Fri, Jul 28, 2006 at 12:32:00PM +0100, Liyang HU wrote:
My current want-it-now 'solution' is to comment out the sole tcSimplifyBracket invocation in ghc/compiler/typecheck/TcSplice.lhs. Clearly this is the wrong approach, seeing as other people would like to use this too. (I presume this will do what I want. I'm still waiting for stage1 to finish building...)
I guess a more constructive approach would be to hack in an alternative unchecked quotation bracket, [s| ... |] say ('s' stands for 'syntax'). If upstream is willing to consider such an extension, I'll get started...
I actually proposed something similar way back: http://www.haskell.org//pipermail/template-haskell/2003-April/000048.html for specifying rewrite rules which weren't all type correct in themselves, but the total effect of fully applying them all was type safe. I didn't push it much as it wasn't that important to me and no-one else seemed interested (plus it felt a bit hackish). There's probably a patch in the archive of one of the lists, but it's probably easier just to recreate it than to track it down and forward-port it.
Any alternative suggestions before I do? :-/
Small point, but I'd prefer [| ... |s] as the middle of [| already has a use.
[2] I am sane, right? I mean, is there any other reason for the internal type-consistency check other than to detect /potential/ errors /earlier/?
I can't remember OTTOMH when the fixities of infix expressions get corrected, i.e. I'm not sure if expressions like (x .+. y .+. z) might get parsed as if the operator bound the wrong way. Thanks Ian
Some quick replies | [2] I am sane, right? I mean, is there any other reason for the | internal type-consistency check other than to detect /potential/ | errors /earlier/? Quite correct. But detecting errors earlier, perhaps much, much earlier, is a Good Thing, right? | I actually proposed something similar way back: | http://www.haskell.org//pipermail/template-haskell/2003-April/000048.htm l | for specifying rewrite rules which weren't all type correct in | themselves, but the total effect of fully applying them all was type | safe. I didn't push it much as it wasn't that important to me and no-one | else seemed interested (plus it felt a bit hackish). Your proposal seems entirely reasonable to me. By not typechecking the quotation at all, it pushes towards the extreme of more flexibility but later error reporting. (MetaML is at the other extreme.) And if that is what you want, it seems like a reasonable thing to me. If you want to commit a patch that does it, go ahead. Please document the change in the manual; and perhaps add a section on the TH wiki page to explain what it's good for. I don't hear a lot about TH these days, but occasionally I hear people saying "I used TH to do X or Y". So I think that is good news; it works well enough to be useful. But I'm sure it could be better in many ways. Simon
participants (3)
-
Ian Lynagh -
Liyang HU -
Simon Peyton-Jones