New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simplifying (un)contractive and (un)inhabitable types #645
Comments
@DavePearce, thanks for the great write up. I agree that the existing algorithm will be much simpler and clearer if split into separate—but interdependent—simplification and contractivity testing phases. I know that's what you suggested before I made the changes in #631, and I regret that I implemented a single combined phase. I may revert some parts of my change to recover the original simplification algorithm that was there before #631, then create a separate contractivity testing phase. I think I should also simplify #631's contractivity testing implementation to use fewer labels. The existing implementation uses four different labels for nodes—unlabeled, none, some, all. Yesterday, when we talked, you advocated using simpler binary labels: contractive, non-contractive. Now that I think about it, I think binary labels would work well and would be better. So I'll put that on my todo list too! Function/method typesRegarding functions types, I think we may be able to deal with them with two rules in our type simplification and contractivity testing. How do the following rules sound? (My thoughts about appropriate rules change daily, but these rules are where I'm at with my thinking right now!)
Examples:
Function/method valuesThe rules above permit function types with However, just because we permit function types with |
Hey @richdougherty ... I updated my original discussion to identify three distinct phases, not two as originally stated. This is good .. we are making progress!!! |
At this stage, I am now going to close this issue. The latest |
❤️ |
(follows on from #631, #406 and is based on work @richdougherty is doing)
Simplifying recursive types in the presence of uncontractive or otherwise uninhabitable types presents something of a challenge. There are two main phases:
T1 <: T2
becomesT1&!T2
which we try and simplify tovoid
.InfList
from Checking for Uninhabitable Types #631). At this stage, it's unclear what to do upon detection of an uninhabited type. Ideally, a warning of some sort would be produced. In practice, we may just treat them asvoid
.We have three steps here and, unfortunately, it seems the latter two may depend on each other:
Contractivity can be completed prior to simplification and inhabitability checking. This test is done using a graph propagation algorithm (e.g. depth-first search). However, it cannot be implemented (as far as I'm aware) using simplification based on rewrite rules.
Simplification cannot be completed until non-contractive types are reduced to
void
. For example, consider this type:In this case, the type
NullInfList
should reduce tonull
. This can only happen afterInfList
has been identified as non-contractive and, hence, equivalent tovoid
.Inhabitability cannot easily be tested before simplifications. The general pattern here is that we have a union between recursive type, and something which appears to be inhabited. For example:
In this case,
Empty
should be simplified tovoid
. However, the contractivity test is going to treatEmpty
as a simple primitive type which seems to be inhabited.Thus, we can see that we need to iterate these two mechanisms together in unison until a fixpoint is reached.
Functions/Methods
Some types cause a few problems here. In particular, function or method types are interesting because (in some sense) it can make sense for them to be non-contractive. For example, consider this method:
This type is inhabited by the following implementation (for example):
An interesting question here is whether or not such an implementation can ever really be considered as useful ... ?
The text was updated successfully, but these errors were encountered: