Zulip Chat Archive

Stream: new members

Topic: Multually defined inductive type and function


Eric Wieser (Jun 26 2020 at 12:59):

Is it possible to use mutual inductive where one branch is a type and the other is a def? Or does that question not make sense?

Chris B (Jun 26 2020 at 13:02):

More the latter, but can you post an example of what you'd like to do?

Scott Olson (Jun 26 2020 at 13:02):

I know for sure this is possible in Agda, but Lean's mutual syntax seems less flexible in these examples: https://leanprover.github.io/theorem_proving_in_lean/induction_and_recursion.html#mutual-recursion

Scott Olson (Jun 26 2020 at 13:03):

The Agda docs have a TypeCode/Interpretation example: https://agda.readthedocs.io/en/v2.6.1/language/mutual-recursion.html#mutual-recursion

Eric Wieser (Jun 26 2020 at 13:06):

Here's my best attempt:

mutual inductive blade_new, blade_is_perp
with blade : nat  Type u
| scalar : G₀  blade_new 0
| vector : G₁  blade 1
-- takes a vector, n+1 blade, and a proof that the vector and n+1 blade are perpendicular
| graded {n : } : Π (v : G₁) (b : blade_new (n + 1)), (blade_is_perp v b)  blade_new (n + 2)

-- a proof of perpendicularity is either
with blade_is_perp : Π  {n : },  (v : G₁) (b : blade_new (n + 1)), sorry : sorry
-- a proof that `v` is perpendicular to the sole element of `blade_new.vector`
-- a proof that both:
--   `v` is perpendicular to the v argument of `blade_new.graded`
--   `v` is perpendicular to the b argument of `blade_new.graded`

Eric Wieser (Jun 26 2020 at 13:08):

I'm not really sure how to write the type of blade_is_perp

Reid Barton (Jun 26 2020 at 13:08):

This makes sense (it's called induction-recursion) but Lean doesn't support it.

Reid Barton (Jun 26 2020 at 13:11):

(are blade and blade_new supposed to be the same thing?)

Eric Wieser (Jun 26 2020 at 13:11):

I suppose a perhaps simpler example of my problem is constructing a list along with a proof that a relation is satisfied between every pair of elements

Reid Barton (Jun 26 2020 at 13:12):

You can emulate induction-recursion in Lean in various ways, but the easiest to work with in a case like this will just be to build it directly as {l : list A // l.pairwise r} -- or whatever the actual name is.

Chris B (Jun 26 2020 at 13:19):

Kind of a reiteration of what he said, but often you can state the definition you want in a more general way than you actually plan to use it, then declare the inductive such that it uses the specialized form of the definition. Mario Carneiro helped me with similar solution a little while back, where IFunc gets declared with a type parameter (A) that then gets filled in as the inductive : https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/Lea%28r%29n.20you.20a.20scheme/near/190326502

Patrick Massot (Jun 26 2020 at 13:30):

To be honest, I've always had the impression that people interested in those things should play with Agda instead of Lean. This part part of Lean seems broken and completely orthogonal to what works great in Lean.

Reid Barton (Jun 26 2020 at 13:36):

In this case the "workaround" of using a list + separately defined property is also more convenient in practice anyways.

Eric Wieser (Jun 26 2020 at 13:53):

@Reid Barton, is it generally better to reuse existing inductive types like list instead of defining my own?

Johan Commelin (Jun 26 2020 at 13:54):

Depends on what you want to do. If you reuse stuff, you can also reuse a lot of lemmas.

Johan Commelin (Jun 26 2020 at 13:54):

And sometimes "a lot" means > 4000 lines of code.

Eric Wieser (Jun 26 2020 at 13:55):

And can I use pairwise on vector instead of list?

Johan Commelin (Jun 26 2020 at 13:57):

Well, a vector is defined in terms of lists, so "yes".

Kevin Buzzard (Jun 26 2020 at 13:58):

you could easily make vector.pairwise

Johan Commelin (Jun 26 2020 at 13:58):

But you might need to extract the listy part out of the vector

Eric Wieser (Jun 26 2020 at 14:01):

@Reid Barton: I don't fully understand the syntax you have, mind giving me a really simple #check command that I can put that into?

Eric Wieser (Jun 26 2020 at 14:02):

parameters (l : nat)
#check (l : list nat // l.pairwise eq)

is giving me "invalid expression"

Kevin Buzzard (Jun 26 2020 at 14:03):

you have two l's?

Reid Barton (Jun 26 2020 at 14:03):

{}, not ()

Kevin Buzzard (Jun 26 2020 at 14:03):

#check {l : list ℕ // l.pairwise eq}

Johan Commelin (Jun 26 2020 at 14:04):

@Gabriel Ebner Can we rip parameter out of core? [/joking]

Johan Commelin (Jun 26 2020 at 14:04):

@Eric Wieser (Note that parameters will be gone in lean 4.)

Johan Commelin (Jun 26 2020 at 14:05):

In general, it's advised to use variables instead.

Eric Wieser (Jun 26 2020 at 14:10):

Oh, I assumed the {} was an argument declaration like ()

Eric Wieser (Jun 26 2020 at 14:10):

But here it's part of the type itself. I haven't seen this type of Type before - is there somewhere in the docs I can read about the syntax?

Kevin Buzzard (Jun 26 2020 at 14:11):

It's notation for subtype

Reid Barton (Jun 26 2020 at 14:11):

You could also just make a custom structure.

Reid Barton (Jun 26 2020 at 14:12):

Reuse of list lemmas is one advantage, but this style is also just easier to work with than a fancy inductive-recursive definition, at least when the inductive-recursive definition isn't buying you any additional expressive power.

Kevin Buzzard (Jun 26 2020 at 14:12):

I'm not sure it's easy to see the {x : X // p x} notation for @subtype X p defined in Lean, it might be baked in somehow?

Reid Barton (Jun 26 2020 at 14:13):

For example, you can replace the list by a propositionally equal one and then transport the proof of the property without having to rebuild the entire inductive structure.

Eric Wieser (Jun 26 2020 at 14:13):

Johan Commelin said:

But you might need to extract the listy part out of the vector

How do I do that?

Eric Wieser (Jun 26 2020 at 14:14):

(v : list ℕ) didn't work, so I guess there's no coe defined?

Reid Barton (Jun 26 2020 at 14:15):

There is for subtype itself, but if you introduced a def for it then there isn't for your def.

Reid Barton (Jun 26 2020 at 14:15):

v.val or v.1 or add a has_coe instance defined to be one of these.

Eric Wieser (Jun 26 2020 at 14:16):

Is there any way to get autocomplete to help me there?

Eric Wieser (Jun 26 2020 at 14:16):

Hitting tab after the dot gave me a massive list

Reid Barton (Jun 26 2020 at 14:16):

Yes, define your own structure instead of reusing subtype :upside_down:

Reid Barton (Jun 26 2020 at 14:16):

Otherwise, there is nothing for autocomplete to know (it isn't smart enough to unfold definitions).

Eric Wieser (Jun 26 2020 at 14:17):

What is the structure equivalent to {x : X // p x}?

Kevin Buzzard (Jun 26 2020 at 14:17):

subtype p

Johan Commelin (Jun 26 2020 at 14:18):

structure foo :=
(l : list X)
(p : l.pairwise eq)

Johan Commelin (Jun 26 2020 at 14:18):

(modulo typos)

Eric Wieser (Jun 26 2020 at 14:18):

Thanks, that now seems obvious

Eric Wieser (Jun 26 2020 at 14:18):

I was trying to work out how I could constrain the l field

Kevin Buzzard (Jun 26 2020 at 14:19):

oh you mean rolling your own?

Kevin Buzzard (Jun 26 2020 at 14:19):

the joys of dependent types

Eric Wieser (Jun 26 2020 at 14:19):

But obviously that's not necessary, if you pass an l that doesn't satisfy the pairwise requirement, then you just get stuck producing a p

Scott Olson (Jun 26 2020 at 14:19):

This is the actual definition of subtype in Lean for reference: https://github.com/leanprover-community/lean/blob/de6c873a57fda86c20dc93f4660ab257ef8e8995/library/init/core.lean#L270-L271

Reid Barton (Jun 26 2020 at 14:52):

By the way, note that vector is defined in the Lean core library as a subtype and not an inductive family indexed on nat, even though Lean supports those just fine, for the same reason: it's easier to use.

Johan Commelin (Jun 26 2020 at 15:04):

@Eric Wieser Why are you actually interested in lists of which all elements are pairwise equal? They don't seem very interesting to me...

Eric Wieser (Jun 27 2020 at 09:44):

@Johan Commelin: That was a contrived example, what I actually care about is list where elements have a pairwise dot product of zero

Johan Commelin (Jun 27 2020 at 09:47):

Ok, that sounds a lot more interesting :wink:


Last updated: Dec 20 2023 at 11:08 UTC