[Haskell-cafe] Retrieving information about type families

12 views
Skip to first unread message

Alejandro Serrano Mena

unread,
Jul 23, 2014, 2:48:39 PM7/23/14
to haskell-cafe
Dear Café,
My quest for obtaining information about type families continues.
Now I have a simple question: how should I access the information about "type instance"s via the GHC API? My aim is to do so after type checking, that is, to get that information from a TypecheckedModule. However, I haven't yet been able to touch the right buttons to make it work ;(

Thanks in advance,
Alejandro

Richard Eisenberg

unread,
Jul 23, 2014, 5:39:19 PM7/23/14
to Alejandro Serrano Mena, haskell-cafe
Does FamInstEnv.lookupFamInstEnv work for you? You will also probably want FamInst.tcGetFamInstEnvs.

Richard
> _______________________________________________
> Haskell-Cafe mailing list
> Haskel...@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
Haskel...@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Niklas Haas

unread,
Jul 23, 2014, 8:03:29 PM7/23/14
to haskell-cafe

In Haddock we get this information out of md_fam_insts, which you can
get out of ModDetails - we access this from a TypecheckedModule using
tm_internals_. I'm not sure if there's a cleaner way, but I couldn't
find one and this seems to work.

Alejandro Serrano Mena

unread,
Jul 25, 2014, 12:13:28 PM7/25/14
to Richard Eisenberg, haskell-cafe
Thanks for the help! At the end I'm trying to get the information from a RenamedSource (so I can still get source locations) and then get type information using TcHsType. I haven't succedeed yet, but I think I'm on the way!

Alejandro Serrano Mena

unread,
Jul 26, 2014, 4:58:08 AM7/26/14
to Richard Eisenberg, haskell-cafe
I'm still struggling with getting the right information. My aim is to know the kind of a specific variable in a type instance defintion. For example, if I get:

type family F (x :: Bool)
type instance F y = ()
                ^

where ^ marks the point from where I want the information, I want to get "y has kind Bool". 

The approach I'm taking is obtaining the LHsType Name from the specific position in the RenamedSource of the file. Then, I'm trying to convert that LHsType Name to a Type using functions in HscTypes, but I always get complaints about not existing variables.

In the past, I implemented something similar for normal functions. However, in that case I could get the information directly from TypecheckedSource, by querying for a pattern variable with the right location. However, in the TypecheckedSource there's no information about type families at all :( My other possibility seems to use the ModuleInfo, but in those places there's no information of location :(

Is there any way to achieve what I'm trying to do (get the kind of a specific type variable in the LHS of a type family instance, where the variable is given by its position in the source code)?

Thanks in advance.

Richard Eisenberg

unread,
Jul 27, 2014, 10:01:31 AM7/27/14
to Alejandro Serrano Mena, haskell-cafe
Ah, yes, that is a harder nut to crack. You would need to bring the type variables in type patterns into scope before typechecking. See the code for tc_fam_ty_pats in TcTyClsDecls for how this is done normally, but it's rather involved.

As for querying existing structures, you may have a hard time. The problem is that types are handled differently from terms. Terms are typechecked and converted from HsExpr Name to HsExpr Id. The HsExpr Id has been typechecked and thus has stable type information. But, because it's a variant of HsExpr, it still has location information. HsExpr Id is then desugared into CoreExpr, which has no location information.

Types, on the other hand, are checked and desugared simultaneously. This is necessary because typechecking needs to be able to compare types, and we wouldn't want to try to compare HsTypes for equality. So, instead of going through an HsType Id formation, the typechecker goes straight from HsType Name to Type (the Core type type). `Type`, of course, has no location information. So, you won't be able to query by location.

But, I just thought of a way out: type family instances are compiled into CoAxioms, which *do* store location information. The list of CoAxioms should be available from the ModuleInfo via modInfoTyThings. Or, you can get a CoAxiom out of a FamInst if you have that handy. An open type family instance's CoAxiom will have one branch. Then, you can look at the tyvars (cab_tvs) and types (cab_lhs) to triangulate to the bit that you want. It's quite possible that the `Name`s of the tyvars have the location you're looking for. Be careful, because the list of tyvars includes kind variables here, which are omitted in the source. isKindVar should be helpful in filtering these out.

I hope this helps!
Richard

Alejandro Serrano Mena

unread,
Jul 27, 2014, 4:23:43 PM7/27/14
to Richard Eisenberg, haskell-cafe
Thanks for such a detailed answer :)

I'll try to put this in practice as soon as possible
Reply all
Reply to author
Forward
0 new messages