feat: more expressive semiOutParam attribute for ipm_class declarations#513
Open
alvinylt wants to merge 13 commits into
Open
feat: more expressive semiOutParam attribute for ipm_class declarations#513alvinylt wants to merge 13 commits into
semiOutParam attribute for ipm_class declarations#513alvinylt wants to merge 13 commits into
Conversation
…with a Boolean value indicating negation
…amIPM` may involve pattern matching, conditionals, etc.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The
InOutdatatype defined inProofModeM/SynthInstance.leanis used along withsemiOutParamin IPM type class declarations. Currently, we are reusing the attributesemiOutParamfrom the core Lean libraries (Init.Prelude), except that the semi-output parameters must be preceded by anInOutvalue so that it is clear whether particular type class instances require that parameter to be an input or an output.The type class
IsOp, introduced in PR #401, is an example wheresemiOutParamis used:We express
IsOp .in a .out b1 .out b2for the splitting operation andIsOp .out a .in b1 .in b2for the merging operation. If we would like to use the type class for both directions, then currently the only way to do that is to parameterise all threeInOutarguments. That is,IsOp ioa a iob1 b1 iob2 b2whereioa,iob1andiob2are arbitrary. However, this is quite inelegant as we know thatb1andb2must always be the opposite ofa.My suggestion with this PR is to modify
semiOutParamto remove the restriction that theInOutvalue must be the immediately preceding argument. Instead, we have thesemiOutParamIPMattributes with two more explicit arguments to specify whichInOutvalue to use. Withio : InOut := .in,semiOutParamIPM io α false(orsemiOutParamIPM io α) refers to an input parameter andsemiOutParamIPM io α truerefers to an output parameter. Likewise, withio : InOut := .out,semiOutParamIPM io α false(orsemiOutParamIPM io α) refers to an output parameter andsemiOutParamIPM io α truerefers to an input parameter.In fact, there is no longer any restriction for the
InOutvalue to be a parameter in the type signature of the type class. In other words, we are able to use pattern matching, conditional branching and any reducible function to map other types of values to anInOutvalue.With this design,
IsOpis reformulated as follows, whered : IsOp.Directionis either.mergeor.split.There is then no need for one to think about the underlying details of type class synthesis when defining an
IsOpinstance.There are six IPM type classes in the codebase that use semi-output parameters.
AsEmpValidFromWandIntoWandFromAssumptionFromPureIsOpIn fact, there is a similar situation with
AsEmpValid, where thePROPandbialways practically have the same type class synthesis direction. As a result, it has also benefited from this PR:This is meant to just be a syntactic improvement, so there should not be any impact on the type class synthesiser's behaviour. The core of this implementation is the type signature parsing in
ProofModeM/SynthInstanceAttr.lean. Since we now havesemiOutParamIPM, any use ofsemiOutParamin type class declarations with theipm_classannotation is explicitly rejected to avoid confusion.A caveat is that, for regular type class declarations (i.e., those without the
ipm_classannotation), the attributesemiOutParamIPMis ignored. These two attributes are relevant to IPM type classes only and should not be used for regular, non-IPM type classes anyway.As we are not reusing Lean's built-in
semiOutParamattribute, a side effect is that the built-in type class synthesiser is unable to recognise that an argument is a semi-output parameter. This is a problem when an IPM type class is defined in terms of some non-IPM type classes. In this case, the type class synthesis for the non-IPM type classes by default uses the built-in type class synthesiser. Originally, with thesemiOutParamattribute, Lean's built-in synthesiser is able to defer a premise whose type still mentions an unresolved semi-out parameter. This is whysynthInstanceMainCoreis slightly modified to handle the deferral explicitly.Checklist
authorssection of any appropriate files