I updated a personal project to use squeal 0.8.1.0 and was alarmed that one slightly larger file ran out of memory when trying to compile. This was rather surprising as I expected no change when the file compiled. After some experimentation, I tracked it to the following:
MismatchError is used even in the happy path, because we can't differentiate between the types matching and types not matching with our instances (since we rely on fundeps to be able to set the field as matching)
We were calculating PrettyPrintInfo fieldsbefore checking if our found and expected were equal. This meant we were always calculating PrettyPrintInfo fields
PrettyPrintInfo fields does a sort, so it's relatively expensive
So between all of those, it was blowing up compile time memory usage and time.
To fix it, we use another layer of type families to check for our found equaling our expected first, and only then worry about calculating pretty printing info. This means that calculation is relegated to the error case.
HasParameter doesn't have the same issue because it doesn't pretty print, and LookupFailedError doesn't either because it's part of the constraints for an instance head that is only matched in the case of an error.
I updated a personal project to use squeal
0.8.1.0
and was alarmed that one slightly larger file ran out of memory when trying to compile. This was rather surprising as I expected no change when the file compiled. After some experimentation, I tracked it to the following:MismatchError
is used even in the happy path, because we can't differentiate between the types matching and types not matching with our instances (since we rely on fundeps to be able to set the field as matching)PrettyPrintInfo fields
before checking if ourfound
andexpected
were equal. This meant we were always calculatingPrettyPrintInfo fields
PrettyPrintInfo fields
does a sort, so it's relatively expensiveSo between all of those, it was blowing up compile time memory usage and time.
To fix it, we use another layer of type families to check for our
found
equaling ourexpected
first, and only then worry about calculating pretty printing info. This means that calculation is relegated to the error case.HasParameter
doesn't have the same issue because it doesn't pretty print, andLookupFailedError
doesn't either because it's part of the constraints for an instance head that is only matched in the case of an error.