Zulip Chat Archive
Stream: Is there code for X?
Topic: Notation idea
Alex Kontorovich (May 23 2024 at 17:59):
One point of friction from human mathematics to formalization is that we can't say things like: Let and let , because aren't types. I wonder if there could be some notation to smooth this out? E.g.
The text "example (U V : Set \C) (f : U \longrightarrow V)" would "under the hood" produce
example (U V : Set ℂ) (f : ℂ → ℂ) (fUV: ∀ u ∈ U, f u ∈ V)
In other words, you would write:
example (U V : Set ℂ) (f : U ⟶ V)
but it would be interpreted as above. Might something like that make sense?... (Yes, it's a trivial point, but I'd think we'd want to remove as many friction points as possible, even the trivial ones?..)
Felix Weilacher (May 23 2024 at 18:29):
The second thing you write should already work. U
and V
will be interpreted as subtypes of C
Mitchell Lee (May 23 2024 at 18:29):
and are types. Or rather, they can already automatically be coerced to types; it's already possible to write f : U → V
. But it's more idiomatic to write f : ℂ → ℂ
(at least in the complex analysis part of mathlib), because it means you don't have to include the hypothesis fUV: ∀ u ∈ U, f u ∈ V
unless it's necessary.
Patrick Massot (May 23 2024 at 18:29):
Note that fUV
can already be spelled more compactly using docs#Set.MapsTo
Patrick Massot (May 23 2024 at 18:30):
And indeed using f : U → V
and relying on the coercion from Set to Type is very painful.
Mitchell Lee (May 23 2024 at 18:36):
One way to do the thing you describe is by making U ⟶ V
a structure, which carries the data of a function f : ℂ → ℂ
and a proof that ∀ u ∈ U, f u ∈ V
. This won't automatically expand the argument into two arguments like you want, but it would still be usable. However, I suspect that the burden of learning this new notation, and the difficulty in convincing everyone to use it rather than (f : ℂ → ℂ) (fUV: ∀ u ∈ U, f u ∈ V)
, would outweigh the minimal gains in the number of characters you have to type.
Mitchell Lee (May 23 2024 at 18:39):
(Also, this might be unnecessarily pedantic, but I think that U ⟶ V
, defined as above, does not behave the way you might expect in all cases. Let A
be any nonempty type and let B
be any empty type. Let U : Set A
and V : Set B
be empty. Then, there is a function f : U → V
, but there is no function f : A → B
satisfying ∀ u ∈ U, f u ∈ V
).
Kyle Miller (May 23 2024 at 19:14):
While we're here, there's a related notion of functions between filters (as filters are "generalized sets"). If you extract the definition morphisms from Pro(Set) and specialize it to filters, it looks like the following. You get both the idea of functions from one subset to another (Res
below) as well as germs of functions at a point (Germ
below).
import Mathlib
open scoped Filter Topology
structure Filter.Fun {α β : Type*} (F₁ : Filter α) (F₂ : Filter β) where
toFun : α → β
tendsto : Filter.Tendsto toFun F₁ F₂
infixr:25 " ⟶ " => Filter.Fun
variable {α β : Type*} (F₁ : Filter α) (F₂ : Filter β)
instance : CoeFun (F₁ ⟶ F₂) fun _ => α → β := ⟨Filter.Fun.toFun⟩
/-- Functions on filters are equivalent if they are eventually equal on the domain. -/
def Filter.Fun.eq {α β : Type*} (F₁ : Filter α) (F₂ : Filter β) (f g : F₁ ⟶ F₂) : Prop :=
∀ᶠ x in F₁, f x = g x
/-- Germs are functions on the neighborhood filter. `Filter.Fun.eq` is the expected equivalence relation for germs. -/
abbrev Germ {α : Type*} [TopologicalSpace α] (x : α) (β : Type*) := 𝓝 x ⟶ (⊤ : Filter β)
/-- Functions from `U` to `V`. -/
abbrev Res (U : Set α) (V : Set β) := 𝓟 U ⟶ 𝓟 V
Adam Topaz (May 23 2024 at 19:17):
What happens if \beta
is empty (but alpha is not) and F_1
is \bot
?
Kyle Miller (May 23 2024 at 19:20):
That's the pathological example that Mitchell mentioned in the comment right before mine.
Adam Topaz (May 23 2024 at 19:20):
Oh yeah I see it now.
Adam Topaz (May 23 2024 at 19:23):
(I for one don't think it's too pathological...)
Eric Wieser (May 23 2024 at 19:49):
Assuming your code doesn't handle that example, is there a version of Filter.Fun that does handle it in the case of general filters?
Adam Topaz (May 23 2024 at 19:53):
The only issue is that when alpha is nonempty and beta is empty then there are no functions from alpha to beta, but there should be a "function" from the empty filter on alpha to any filter on beta.
Adam Topaz (May 23 2024 at 19:56):
You could, for example, use a partial function from alpha to beta, and add some additional conditions to Filter.fun
.
Kyle Miller (May 23 2024 at 20:01):
Yeah, I think partial functions are right (and also can be better since lots of times you don't want to bother with defining a function outside its domain). This might be the correct definition:
structure Filter.Fun {α β : Type*} (F₁ : Filter α) (F₂ : Filter β) where
toFun : α → Option β
tendsto : Filter.Tendsto toFun F₁ (F₂.map Option.some)
Kyle Miller (May 23 2024 at 20:01):
However, this goes in a direction that's not helpful for Alex's f : ℂ → ℂ
.
Kyle Miller (May 23 2024 at 20:04):
But why worry about empty types. All types are inhabited, right? (That's how it is in Isabelle.)
Last updated: May 02 2025 at 03:31 UTC