How to get the declaration of a function using `reify`?
Asked Answered
C

1

12

Function reify allows me to look up information about a given name. For a function the returned value is VarI:

data Info = ... |  VarI Name Type (Maybe Dec) Fixity  | ...

Here I can examine the function's type, and I'd also like to examine its declaration. However, in the 3rd argument to VarI I always see Nothing. Is there a way to get the function's declaration?

Countervail answered 21/11, 2013 at 10:12 Comment(2)
That's an excellent question. I've tried marking the definition INLINE or INLINEABLE, and neither made any difference. I suspect it isn't implemented at all, but I don't know.Gossett
possible duplicate of How to use Template Haskell to get the body of function?Chemisette
L
9

From the template haskell docs on the VarI Info contructor:

A "value" variable (as opposed to a type variable, see TyVarI). The Maybe Dec field contains Just the declaration which defined the variable -- including the RHS of the declaration -- or else Nothing, in the case where the RHS is unavailable to the compiler. At present, this value is always Nothing: returning the RHS has not yet been implemented because of lack of interest.

Looking at the ghc source mirror on github, the string VarI only appears twice, and both in the compiler/typecheck/TcSplice.lhs implementing the reifyThing function:

reifyThing :: TcTyThing -> TcM TH.Info
-- The only reason this is monadic is for error reporting,
-- which in turn is mainly for the case when TH can't express
-- some random GHC extension

reifyThing (AGlobal (AnId id))
  = do  { ty <- reifyType (idType id)
        ; fix <- reifyFixity (idName id)
        ; let v = reifyName id
        ; case idDetails id of
            ClassOpId cls -> return (TH.ClassOpI v ty (reifyName cls) fix)
            _             -> return (TH.VarI     v ty Nothing fix)
    }

reifyThing (AGlobal (ATyCon tc))   = reifyTyCon tc
reifyThing (AGlobal (ADataCon dc))
  = do  { let name = dataConName dc
        ; ty <- reifyType (idType (dataConWrapId dc))
        ; fix <- reifyFixity name
        ; return (TH.DataConI (reifyName name) ty
                              (reifyName (dataConOrigTyCon dc)) fix)
        }

reifyThing (ATcId {tct_id = id})
  = do  { ty1 <- zonkTcType (idType id) -- Make use of all the info we have, even
                                        -- though it may be incomplete
        ; ty2 <- reifyType ty1
        ; fix <- reifyFixity (idName id)
        ; return (TH.VarI (reifyName id) ty2 Nothing fix) }

reifyThing (ATyVar tv tv1)
  = do { ty1 <- zonkTcTyVar tv1
       ; ty2 <- reifyType ty1
       ; return (TH.TyVarI (reifyName tv) ty2) }

reifyThing thing = pprPanic "reifyThing" (pprTcTyThingCategory thing)

Like the template haskell docs said, the value used for that field is always Nothing.

Digging deaper, this code was added in 2003, in what looks like a rewrite of the reify system. So it does appear to be little interest in getting it working since it has been more than 10 years that field has always had the value Nothing. So I'm guessing if you want the feature you will have to implement it yourself (or propose a good use case to the ghc development mailing list that would encourage someone else to do it).

Leper answered 21/11, 2013 at 17:48 Comment(1)
It is quite sad that there is little interest, since it looks like an excellent way to automatically rewrite functions for example.Preemption

© 2022 - 2024 — McMap. All rights reserved.