Folks I'm on the TH warpath, and I'm working on reification. The idea is that 'reify' is not a language construct any more: it's just an ordinary function reify :: Var -> Q Dec This is much better that what we have now, because when you walk over the Dec you may find more Vars, and now you can reify them in turn. Which you absolutely cannot do today. To invoke reify in the first place, you need a Var, and you can get one using the new quote syntax. e.g. reify 'map will give you the declaration for map. In general 'map is very like [| map |], except you get a Var instead of a Q Exp. So (a) it's not monadic, which is jolly convenient, and (b) it gives you the Var v directly rather than a (VarE v), which is also convenient. But it has all the same staging rules as [| ... |]. Question 1 ~~~~~~~ You probably want more info than just the declaration. For functions you'd like to know the type and fixity... so we could instead have reify :: Var -> Q Info data Info = Class Decl | TyCon Decl | Var Type Decl Fixity | DataCon Type Var {- parent tycon -} Fixity | ClassOp Type Var {- parent class -} Fixity | Unknown Would that be a better plan? One could have reifyFixity, reifyType, etc, to get the anciliary bits, but it seems nicer to get the whole lot in one go. It's a bit unclean that given (Class d) it'd be certain that d was of the form ClassD. Any better ideas? Question 2 ~~~~~~~ The type checker may not know the full type of the thing. For example: f x = $( do { i <- reify 'x; ... } ) ..... The type of 'x' isn't known yet. It may get refined by the other "..." parts of f's body, or by f's use. So should we give up and refuse to give you f's type? Or what? NB This can apply to top-level decls too: f = 1+2 $( ... reify 'f... ) g = f + (4::Int) Because of the monomorphism restriction, the type of f is fixed by f's caller, which may be "after" the reification. I'm really not sure what to do here. Simon PS: I've implemented most of this stuff, but I'm holding off committing for fear of annoying those of you using current TH. But I'd like to commit soon. Perhaps anyone wanting a stable TH can use the 6.2 branch? Would that do?
On Wed, Nov 05, 2003 at 05:16:41PM -0000, Simon Peyton-Jones wrote:
Folks
I'm on the TH warpath, and I'm working on reification. The idea is that 'reify' is not a language construct any more: it's just an ordinary function
reify :: Var -> Q Dec
I still prefer "Name" to "Var" (assuming I'm not confused and you can give it the name of a class, type or whatever).
Question 1 ~~~~~~~ reify :: Var -> Q Info
I prefer getting an Info to a Dec, yes.
Question 2 ~~~~~~~ The type checker may not know the full type of the thing. For example:
f x = $( do { i <- reify 'x; ... } ) .....
The type of 'x' isn't known yet. It may get refined by the other "..." parts of f's body, or by f's use.
So should we give up and refuse to give you f's type? Or what?
I think it would be best to give what info is available. I think types that are definitely determined should be distinguishable from those that aren't (e.g. "we know this is type Num a => a" compared to "this is at most Num a => a, but it might turn out to be Int"), but highlighting which component bits are definitely known probably isn't worth the complexity. Thanks Ian
Hi Simon,
I'm on the TH warpath,
Great! And thanks for all the support.
Question 1 ...
I would prefer to get the whole reification all at once, with something like your Info, rather than having separate reifyFixity etc.
Question 2
The type checker may not know the full type of the thing. ... So should we give up and refuse to give you f's type? Or what?
What would be most flexible for the user is to return the best information that is available. In the example:
NB This can apply to top-level decls too: f = 1+2 $( ... reify 'f... ) g = f + (4::Int)
Because of the monomorphism restriction, the type of f is fixed by f's caller, which may be "after" the reification.
it might still be useful to find out that an approximation to the type is f :: Num a => a, even though that isn't the final type. That would suggest something like data TypeQuery a = ExactType a | ApproximationType a But it isn't clear to me whether ghc could even know whether it has a final, exact type! Still, it would be helpful for ghc to gives the best information it has to hand; after all, if the type changes later on it will be a refinement of the type that was reported in the reification. Is this feasible? I'm coming across situations that are analogous to this in Hydra. For example, a defintion might have a top level type like Clocked a => (a,a) -> a, but the a will be refined to something specific, like Stream CMOS, later on. The program transformation really needs to know the (a,a) -> a (and it needs to know that a is in the Clocked class), but it is irrelevant to know the specific type a. So, I would like to get the best type ghc knows.
I'm really not sure what to do here.
Me too - my ideas about the best thing to do often change after I've implemented something and experimented with it. For exactly that reason, it's best for you to go ahead and release the new TH stuff; as long as core functionality isn't removed, I don't mind making changes to working code. Eventually a stable TH will be important, but it's obviously too soon for that now! Best wishes, John
participants (3)
-
Ian Lynagh -
John O'Donnell -
Simon Peyton-Jones