Listing types with or without a certain type class instance?

I have a medium-sized codebase (about 25K LOC) with around 200 different data types, and I want to find all the types which do not have a ToJSON instance. Curious if anyone has ideas for an automated way to accomplish that — perhaps using the GHC API somehow? Because of things like standalone deriving, orphan instances, etc., a simple syntactic analysis is probably not going to cut it.

You might be able to put something together using hiedb (which produces a SQLite database). The result of .hie files would definitely be my choice for the source of this information.

4 Likes

I’ve managed to install hiedb and index all the relevant .hie files into a database. I can use the hiedb tool to list the source locations of all the references to ToJSON, or find the definition of any type; I also figured out how to directly query a list of all the defined data types from the database. I haven’t yet figured out how to extract information about type class instances, but I’ll keep playing with it.

1 Like

Do report back to us, this sounds like a great use case :slight_smile:

There exists the function reifyInstances :: Name -> [Type] -> Q [InstanceDec] (Language.Haskell.TH) which can return all instances of a class which are in scope.

You could use it to view all FromJSON instances in your project if you run it in a module which imports all other modules. However, it does not seem like you can get datatypes which do not satisfy an instance with this method. Maybe you can combine this with the hiedb approach; query all defined data types with hiedb and then subtract the ones found with reifyInstances.

2 Likes

GHCi gives you all instances of a class via :i. Maybe that’s a starting point too.

2 Likes

A dumb solution would be to generate a source file that imports all the types, and then use toJSON on an undefined of each type; try to compile that source file, and the error messages will tell you which types don’t have JSON instances.