Closed ta0kira closed 3 years ago
Looking at TypeInstance.hs
:
requires
and allows
filters aren't explicitly added as guesses; they're added during a recursive type check for the conversion. So, there really isn't a way to treat them specially without short-circuiting the recursive check when the param is inferred. This also means that a pattern match doesn't mean they've been accounted for.defines
filters aren't even looked at in the conversion check; they're only checked during param assignment after inference happens.In other words, filters are treated as the meta-type of the param in the conversion check, and as a type template for the param during param assignment.
Actually, filters are explicitly converted to guesses in inferParamTypes
. Without that, I don't think the inference algorithm would account for the filters at all.
But, since they're always going to be in a top-level "all" with the actual guesses, leaving them out during merging would result in a superset of guesses. This means that mergeInferredTypes
could be updated to filter the final guesses before making a selection.
It would be straightforward to just filter the ranges by attempting to assign their bounds to the param:
Note that restricting the ranges in this manner shoudn't result in any new merge possibilities; therefore, the steps above can just be applied as post-processing before making the final selection.
Incidentally, inference will fail for params with no guesses, e.g., return types with allows
filters. This is fine, because in such situations there really isn't anything to infer. (There would be if expected return types were accounted for in the inference process.)
Since filters in this context are type templates, they don't need to fall within any range constraints; the final guess just needs to match them. In other words, filters shouldn't be used as guesses.
This just means that whatever the guess was otherwise going to be needs to match the filters.
On the other hand, it's unclear if the filter should become the guess in some cases. For example, a requires
filter could further restrict an upper bound, possibly making it compliant.
A few more thoughts:
requires
/allows
filters need to put the filter on the left side so that inferred params cause an error.So, maybe something like this:
For each range [A
,B
]:
A
and B
both satisfy all filters, leave the range as it is.A
satisfies all filters, replace the range with [A
,A
].B
satisfies all filters, replace the range with [B
,B
].Merge the remaining guesses with simplifyUnion
.
Use the existing approach for choosing the best guess.
The new algorithm for param inference (See #100) doesn't allow both upper and lower bounds for param guesses. This means that inference will almost always fail for
requires
filters.On the other hand, I don't know if it's necessary to include the filters as guesses. For example, does success of the pattern match mean that any valid guess for the param will satisfy the filter?
Additionally, should it somehow account for
defines
filters? Perhaps adefines
filter should be an automatic inference failure, since it can't be used in ranges and it requires aconcrete
type. On the other hand, you can still have variance with a concrete type.