Zulip Chat Archive

Stream: new members

Topic: dependent structures


Jake Levinson (Mar 04 2022 at 05:13):

What's the right way to work with dependent / parametrized structures like structure foo (a : α) : ... where α : Type? I have something like that, and sometimes I end up with two foo's using different but equal a's, and I'd like to compare them or work with them.

Here's the sort of thing I mean:

import tactic

variable {α : Type}

def p : α  Prop := sorry
def f : α  α := sorry
lemma fp {a : α} : p a  p (f a) := sorry

structure foo (a : α) :=
  (seq :   )
  (bar : p a)

def new_foo {a : α} (t : foo a) : foo (f a) :=
{ seq := λ n, t.seq (n + 1),
  bar := fp t.bar }

def new_foo' {a : α} (t : foo a) (h : f a = a) : foo a :=
  (congr_arg foo h).mp (new_foo t)

lemma new_foo'_def {a : α} (t : foo a) (h : f a = a) (n : ):
  (new_foo' t h).seq n = t.seq (n+1) := sorry

So by default new_foo produces something of type foo (f a), but occasionally I can get a foo a instead. In the situation I'm in, the new_foo definition is actually quite involved -- that's why I wanted new_foo' to "piggyback" off of it rather than redoing the proof. The situation is loosely along the lines of a : set X and an operation like new_foo ... : foo (insert x a), where sometimes it can be shown that x ∈ a and so this operation should stay in foo a.

But, the congr_arg definition seems... awkward, in particular I don't know how to prove the last sorry as (new_foo' t h).seq is not defeq to (new_foo a).seq. If I do rw [new_foo', new_foo] I get stuck with a goal like

 (_.mp {seq := λ (n : ), t.seq (n + 1), bar := _}).seq n = t.seq (n + 1)

So the eq.mp is in the way of the pattern matching. I suspect I shouldn't be trying to modify the a parameter. Should I be defining

structure foo' :
  (a : α)
  (seq :   )
  (bar : p a)

instead?

Kyle Miller (Mar 04 2022 at 05:50):

One way around this is to use a copy pattern (that's a link to one instance of it). You create a copy function that rewrites the relevant parts to make things definitionally convenient.

For your case, we can re-use seq when we copy it, and then that last sorry can be a mere rfl:

variable {α : Type}

def p : α  Prop := sorry
def f : α  α := sorry
lemma fp {a : α} : p a  p (f a) := sorry

structure foo (a : α) :=
  (seq :   )
  (bar : p a)

def new_foo {a : α} (t : foo a) : foo (f a) :=
{ seq := λ n, t.seq (n + 1),
  bar := fp t.bar }

def foo.copy {a a' : α} (t : foo a) (h : a = a') : foo a' :=
{ seq := t.seq,
  bar := h  t.bar }

def new_foo' {a : α} (t : foo a) (h : f a = a) : foo a :=
(new_foo t).copy h

lemma new_foo'_def {a : α} (t : foo a) (h : f a = a) (n : ):
  (new_foo' t h).seq n = t.seq (n+1) := rfl

Jake Levinson (Mar 04 2022 at 05:53):

Neato, I'll try that in my larger context.

Jake Levinson (Mar 04 2022 at 05:57):

yesssss

Jake Levinson (Mar 04 2022 at 05:59):

That works. Thanks!


Last updated: Dec 20 2023 at 11:08 UTC