Haskell has many great tools for debugging run time performance issues, but what tools/rules of thumb exist for debugging compile time performance issues?
Specifically, the constraint solver in some of my code is taking forever (anywhere from 1-2 seconds to several minutes). I'm pretty sure this is due to how I'm using type families in the constraints, but I have no idea what sort of things are expensive in this context or how to see where the constraint solver is spending its time. My best guess is that one of my operations on type lists is taking quadratic time instead of linear.
Let's see an example of why I suspect the constraint solver. In my files, I have code that looks like:
class ExampleClass a where
type ExampleType a
f :: ExampleType a -> a
data ExampleData (xs :: [a]) = ...
instance
( Constraint1
, Constraint2
, ...
) => ExampleClass (ExampleData xs)
where
type ExampleType (ExampleData xs) = Int
f = undefined
When I load this file into ghci
ghci> :l Example.hs
compilation happens very quickly, much less than 1 second. Then, I execute the following line:
ghci> let test = f Int :: ExampleData
No actual computation is going on, but this still takes a very long time. The more constraints in ExampleData
's instance declaration, the longer it takes. (Actually evaluating test later happens instantly.) The best way I've figured out how to debug these performance issues is by commenting out constraints one-by-one and seeing which ones are causing the performance hit. But this is very time consuming, and when those constraints involve complex type families, it's not really all that informative.
So, is there a better approach I can take to debug this problem?
Edit: It turns out I discovered a bug in GHC. There's a script associated with the bug that demonstrates that the constraint solver is taking quadratic time on inputs that should be linear.