-
Notifications
You must be signed in to change notification settings - Fork 26
Tradeoff of defining types as subobjects #86
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
Open
YaelDillies
wants to merge
10
commits into
master
Choose a base branch
from
tradeoff-of-defining-types-as-subobjects
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
c53c4f0
Tradeoff of defining types as subobjects
YaelDillies 5d922af
missing using
YaelDillies 1088859
clarify that Proj isn't always smooth
YaelDillies 9da3983
footnotes
YaelDillies 12da769
better category
YaelDillies deac25c
uninformative
YaelDillies 8f66873
Merge remote-tracking branch 'origin/master' into tradeoff-of-definin…
YaelDillies 235d45a
Line breaks, description, teaser end
YaelDillies 65ed1b8
better explanation
YaelDillies fe4471b
drop paragraph
YaelDillies File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| --- | ||
| author: 'Yaël Dillies' | ||
| category: 'Papers' | ||
| date: 2024-07-25 14:00:00 UTC+03:00 | ||
| description: '' | ||
| has_math: true | ||
| link: '' | ||
| slug: tradeoff-of-defining-types-as-subobjects | ||
| tags: '' | ||
| title: Tradeoffs of defining types as subobjects | ||
| type: text | ||
| --- | ||
|
|
||
| It often happens in formalisation that a type of interest is a subobject of another type of interest. For example, the unit circle in the complex plane is naturally a submonoid (nevermind that it is actually a subgroup, we currently can't talk about subgroups of fields). | ||
YaelDillies marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| What is the best way of defining this unit circle in terms of `Complex`? This blog post examines the pros and cons of the available designs. | ||
|
|
||
| ## The available designs | ||
|
|
||
| We will illustrate the various designs using the "circle in the complex plane" example. | ||
|
|
||
| The first option, most loyal to the description of the unit circle as a submonoid of the complex plane, is to simply define the unit circle as a `Submonoid Complex`. We will call the "Subobject design". | ||
|
|
||
| ```lean | ||
| -- Subobject design | ||
| def circle : Submonoid Complex where | ||
| carrier := {x : Complex | ‖x‖ = 1} | ||
| one_mem' := sorry | ||
| mul_mem' := sorry | ||
| ``` | ||
|
|
||
| The second obvious choice would be to define the unit circle as a custom structure. We call this the "Custom Structure" design. | ||
|
|
||
| ```lean | ||
| -- Custom Structure design | ||
| structure Circle : Type where | ||
| val : Complex | ||
| norm_val : ‖val‖ = 1 | ||
| ``` | ||
|
|
||
| Finally, an intermediate option would be to define it as the coercion to `Type` of a subobject. We call this the "Coerced Subobject" design. | ||
|
|
||
| ```lean | ||
| -- Coerced Subobject design | ||
| def Circle : Type := circle -- possibly replacing `circle` by its definition | ||
| ``` | ||
|
|
||
| ## Typeclass search | ||
|
|
||
| In the Subobject design, all instances about `circle` are actually about `↥circle` where `↥` is [`CoeSort.coe`](https://leanprover-community.github.io/mathlib4_docs/find/?pattern=CoeSort.coe#doc). Eg `Foo circle` is secretly `Foo ↥circle`. This makes the head symbol be `CoeSort.coe`, meaning that typeclass search will try unifying *every* `Foo ↥someSubobject` instance with `Foo ↥circle`. In doing so, it will try unifying *every* subobject `someSubobject` with a `Foo` instance with `circle`. This is potentially really expensive. | ||
YaelDillies marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| The Coerced Subobject and Custom Structure designs do not suffer from this performance penalty. | ||
|
|
||
| See [#12386](https://github.com/leanprover-community/mathlib4/pull/12386) for an example where switching from the Subobject design (`ringOfIntegers`) to the Coerced Subobject design (`RingOfIntegers`) dramatically increased performance. | ||
|
|
||
| ## Dot notation | ||
|
|
||
| In the Subobject design, `x : circle` really means `x : ↥circle`, namely that `x` has type `Subtype _`. This means that dot notation `x.foo` resolves to `Subtype.foo x` rather than the expected `circle.foo x`. | ||
|
|
||
| The Coerced Subobject and Custom Structure designs do not suffer from this (unexpected) behavior. | ||
|
|
||
| See [#15021](https://github.com/leanprover-community/mathlib4/pull/15021) for an example where switching from the Subobject design (`ProbabilityTheory.kernel`) to the Custom Structure design (`ProbabilityTheory.Kernel`) was motivated by access to dot notation. | ||
|
|
||
| ## Custom named projections | ||
|
|
||
| In the Subobject and Coerced Subobject designs, the fields of `↥circle`/`Circle` are `val` and `property`, as coming from `Subtype`. This leads to potentially uninforming code of the form | ||
YaelDillies marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ```lean | ||
| -- Subobject design | ||
| def foo : circle where | ||
| val := 1 | ||
| property := by simp | ||
|
|
||
| -- Coerced subobject design | ||
| def bar : Circle where | ||
| val := 1 | ||
| property := by simp | ||
| ``` | ||
|
|
||
| In the Custom Structure design, projections can be custom-named, leading to more informative code: | ||
| ```lean | ||
| def baz : Circle where | ||
| val := 1 | ||
| norm_val := by simp | ||
| ``` | ||
|
|
||
| ## Generic instances | ||
|
|
||
| In the Coerced Subobject and Custom Structure designs, generic instances about subobjects do not apply and must be copied over manually. In the Coerced Subobject design, they can easily be transferred/derived: | ||
| ```lean | ||
| def Circle : Type := circle | ||
| deriving TopologicalSpace | ||
|
|
||
| instance : MetricSpace Circle := Subtype.metricSpace | ||
| ``` | ||
|
|
||
| In the Custom Structure design, these instances must be either copied over manually or transferred some kind of isomorphism. | ||
YaelDillies marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| The Subobject design, by definition, lets all generic instances apply. | ||
|
|
||
| ## Conclusion | ||
|
|
||
| Here is a table compiling the above discussion. | ||
|
|
||
| | Aspect | Subobject | Coerced Subobject | Custom Structure | | ||
| |--|--|--|--| | ||
| | Typeclass search | Possibly expensive | Fast | Fast | | ||
| | Dot notation | ✗ | ✓ | ✓ | | ||
| | Custom named projections | ✗ | ✗ | ✓ | | ||
| | Generic instances | automatic | easy to transfer | hard to transfer but could be improved | | ||
|
|
||
| In conclusion, the Custom Structure design is superior in performance and usability at the expense of a one-time overhead cost when transferring generic instances. The Subobject design is still viable for types that see little use, so as to avoid the instance transferring cost. Finally, the Coerced Subobject is a good middle ground when having custom named projections is not particularly necessary. It could also reasonably be used as an intermediate step when refactoring from the Subobject design to the Custom Structure design. | ||
|
|
||
| ## Further concerns | ||
|
|
||
| Subobjects are not the only ones having a coercion to `Type`: Concrete categories are categories whose objects can be interpreted as types, and there usually is a coercion from such a category to `Type`. | ||
|
|
||
| For example, [`AlgebraicGeometry.Scheme`](https://leanprover-community.github.io/mathlib4_docs/find/?pattern=AlgebraicGeometry.Scheme#doc) sees widespread use in algebraic geometry and [`AlgebraicGeometry.Proj`](https://leanprover-community.github.io/mathlib4_docs/find/?pattern=AlgebraicGeometry.Proj#doc) is a term of type `Scheme` that is also used as a type. | ||
|
|
||
| This raises issues of its own, as `Proj` is (mathematically) also a smooth manifold. Since terms only have one type, we can't hope to have both `Proj : Scheme` and `Proj : SmoothMnfld` (this last category does not exist yet in Mathlib). One option would be to have a separate `DifferentialGeometry.Proj` of type `SmoothMnfld`. Another one would be to provide the instances saying that `AlgebraicGeometry.Proj` is a smooth manifold. | ||
YaelDillies marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
YaelDillies marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
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.
Uh oh!
There was an error while loading. Please reload this page.