Zulip Chat Archive

Stream: maths

Topic: defining the category ConvGroup


Bernd Losert (Jan 02 2022 at 10:16):

So, I have this code:

import tactic
import category_theory.concrete_category.bundled
import algebra.group.hom
import deprecated.group
import order.filter.partial
import algebra.support

noncomputable theory
open set function filter classical option category_theory
open_locale classical filter

universe u

variables {X Y Z : Type*}

set_option old_structure_cmd true

structure convergence_space (X : Type*) :=
(converges : filter X  X  Prop)
(pure_converges :  x, converges (pure x) x)
(le_converges :  { 𝒢},   𝒢   {x}, converges 𝒢 x  converges  x) -- ℱ ≤ 𝒢 means 𝒢 ⊆ ℱ

attribute [ext] convergence_space
attribute [class] convergence_space

open convergence_space

def continuous [p : convergence_space X] [q : convergence_space Y] (f : X  Y) : Prop :=
 {x} {}, p.converges  x  q.converges (map f ) (f x)

lemma continuous.comp
[p : convergence_space X] [q : convergence_space Y] [r : convergence_space Z] {g : Y  Z} {f : X  Y}
(hg : continuous g) (hf : continuous f) : continuous (g  f) := begin
  assume x : X,
  assume  : filter X,
  assume : p.converges  x,
  have : q.converges (map f ) (f x), from hf this,
  have : r.converges (map g (map f )) (g (f x)), from hg this,
  convert this,
end

instance [p : convergence_space X] [q : convergence_space Y] : convergence_space (X × Y) := sorry

class has_continuous_mul (X : Type*) [convergence_space X] [has_mul X] : Prop :=
(continuous_mul : continuous (λ p : X × X, p.1 * p.2))

class convergence_group (G : Type*) [convergence_space G] [group G] extends has_continuous_mul G : Prop :=
(continuous_inv : continuous (has_inv.inv : G  G))

structure ConvGroup :=
(carrier : Type*)
[is_group : group carrier]
[is_convergence_space : convergence_space carrier]
[is_convergence_group : convergence_group carrier]

instance (G : ConvGroup) : group G.carrier := G.is_group
instance (G : ConvGroup) : convergence_space G.carrier := G.is_convergence_space
instance : has_coe_to_sort ConvGroup Type* := ConvGroup.carrier

namespace ConvGroup

structure hom (G H : ConvGroup) :=
(to_fun : G  H)
(to_fun_continuous : continuous to_fun)
(to_fun_group_hom : is_monoid_hom to_fun)

instance (G H : ConvGroup) : has_coe_to_fun (hom G H) (λ _, G  H) := hom.to_fun

end ConvGroup

instance : category ConvGroup := {
  hom := ConvGroup.hom,
  comp := λ G H K f g, {
    to_fun := g  f,
    to_fun_continuous := begin
      exact continuous.comp (g.to_fun_continuous) (f.to_fun_continuous), -- THIS IS WHERE I AM STUCK
    end,
    to_fun_group_hom := sorry,
  },
  id := λ G, {
    to_fun := λ x, x,
    to_fun_continuous := sorry,
    to_fun_group_hom := sorry,
  },
}

I get some error about an invalid type ascription, which is weird because I am not using any in the proof. I don't know what to do here. Help!

Kevin Buzzard (Jan 02 2022 at 11:56):

Can you post the error?

Bernd Losert (Jan 02 2022 at 12:09):

/Users/bernd/Repositories/convergence/src/test.lean:42:0: warning: declaration 'prod.convergence_space' uses sorry
/Users/bernd/Repositories/convergence/src/test.lean:79:12: error: invalid type ascription, term has type
  (ConvGroup.carrier.convergence_space G).converges ?m_1 ?m_2 
  (ConvGroup.carrier.convergence_space K).converges (map (g.to_fun  f.to_fun) ?m_1) ((g.to_fun  f.to_fun) ?m_2)
but is expected to have type
  continuous (g  f)
state:
G H K : ConvGroup,
f : G  H,
g : H  K
 continuous (g  f)

David Wärn (Jan 02 2022 at 12:30):

The problem is with the brackets in your definition of continuous. Change it to ∀ ⦃x ℱ⦄.

Bernd Losert (Jan 02 2022 at 12:35):

Oh wow. This is my first time running into this kind of problem. I forgot what ⦃ ⦄ are used for.

Bernd Losert (Jan 02 2022 at 12:47):

OK, I found an explanation here: https://leanprover.github.io/theorem_proving_in_lean/interacting_with_lean.html#more-on-implicit-arguments. However, I'm still confused why it fixes my issue.

Patrick Massot (Jan 02 2022 at 16:17):

I would say this ⦃ ⦄ trick is an accidental workaround. This is an elaborator bug, your code should work (and you can make it work it you use @ to help. Your definition of continuity is known to bring elaboration issues. That's why continuous is a structure in mathlib. You can use the following code:

import tactic
import category_theory.concrete_category.bundled
import algebra.group.hom
import deprecated.group
import order.filter.partial
import algebra.support

noncomputable theory
open set function filter classical option category_theory
open_locale classical filter

universe u

variables {X Y Z : Type*}

set_option old_structure_cmd true

@[ext] class convergence_space (X : Type*) :=
(converges : filter X  X  Prop)
(pure_converges :  x, converges (pure x) x)
(le_converges :  { 𝒢},   𝒢   {x}, converges 𝒢 x  converges  x) -- ℱ ≤ 𝒢 means 𝒢 ⊆ ℱ


open convergence_space


structure continuous [convergence_space X] [convergence_space Y] (f : X  Y) : Prop :=
(cvg :  {x} {}, converges  x  converges (map f ) (f x))

lemma continuous.comp [convergence_space X] [convergence_space Y] [convergence_space Z]
  {g : Y  Z} {f : X  Y} (hg : continuous g) (hf : continuous f) : continuous (g  f) :=
λ x  h, hg.cvg (hf.cvg h)⟩


instance [convergence_space X] [convergence_space Y] : convergence_space (X × Y) := sorry

class has_continuous_mul (X : Type*) [convergence_space X] [has_mul X] : Prop :=
(continuous_mul : continuous (λ p : X × X, p.1 * p.2))

class has_continuous_smul (S X : Type*) [has_scalar S X] [convergence_space S] [convergence_space X] : Prop :=
(continuous_smul : continuous (λ p : S × X, p.1  p.2))

class convergence_group (G : Type*) [convergence_space G] [group G] extends has_continuous_mul G : Prop :=
(continuous_inv : continuous (has_inv.inv : G  G))

structure ConvGroup :=
(carrier : Type*)
[is_group : group carrier]
[is_convergence_space : convergence_space carrier]
[is_convergence_group : convergence_group carrier]

instance (G : ConvGroup) : group G.carrier := G.is_group
instance (G : ConvGroup) : convergence_space G.carrier := G.is_convergence_space
instance : has_coe_to_sort ConvGroup Type* := ConvGroup.carrier

namespace ConvGroup

structure hom (G H : ConvGroup) :=
(to_fun : G  H)
(to_fun_continuous : continuous to_fun)
(to_fun_group_hom : is_monoid_hom to_fun)

instance (G H : ConvGroup) : has_coe_to_fun (hom G H) (λ _, G  H) := hom.to_fun

lemma hom.continuous {G H : ConvGroup} (f : hom G H) : continuous f := f.to_fun_continuous

def hom.comp {G H K : ConvGroup} (g : hom H K) (f : hom G H) : hom G K :=
{ to_fun := g  f,
  to_fun_continuous := g.continuous.comp f.continuous,
  to_fun_group_hom := f.to_fun_group_hom.comp g.to_fun_group_hom }

end ConvGroup

instance : category ConvGroup := {
  hom := ConvGroup.hom,
  comp := λ G H K f g, g.comp f,
  id := λ G, {
    to_fun := λ x, x,
    to_fun_continuous := sorry,
    to_fun_group_hom := sorry,
  },
}

Patrick Massot (Jan 02 2022 at 16:18):

Note that I also removed all your instance variable names. If you really want this to be a class then you should very rarely need to name instance inputs.

Bernd Losert (Jan 02 2022 at 16:26):

Ah, I was wondering why continuous was a structure in instead of a plain Prop. So what is the general advice here? Use a structure or use these weak implicit arguments?


Last updated: Dec 20 2023 at 11:08 UTC