Zulip Chat Archive

Stream: new members

Topic: noob question


Wojciech Nawrocki (Sep 04 2018 at 15:02):

Hello! Very new to Lean and logic in general; i'm interested in how i can find the function names that i might need for various deduction steps (e.g. and.intro), since the std/maths library sections of "theorem proving in lean" are empty :anguished: in particular, i want to go from ¬p → false to p

Patrick Massot (Sep 04 2018 at 15:04):

https://github.com/leanprover/lean/blob/master/library/init/classical.lean#L160

Patrick Massot (Sep 04 2018 at 15:05):

This is in directory init of the core library, so you don't have to import anything, but it's in namespace classical so you need either open the namespace or use the full name

Johan Commelin (Sep 04 2018 at 15:05):

Welcome to Lean! Figuring out the names of lemmas etc is still a bit of a dark art. Most of us are learning by asking lots of questions here. So feel free to ask more :smiley:

Patrick Massot (Sep 04 2018 at 15:06):

Yes, welcome, and don't let constructivist Kenny scare you!

Johan Commelin (Sep 04 2018 at 15:06):

Also, don't mind about Kenny. He doesn't like the stuff in classical.lean. But he's a nice guy if you ignore that bit :rolling_on_the_floor_laughing:

Bryan Gin-ge Chen (Sep 04 2018 at 15:08):

See also this discussion in the book "Logic and Proof".

Johan Commelin (Sep 04 2018 at 15:12):

There's a subtle difference between constructive mathematics and constructive pedagogy.

Rob Lewis (Sep 04 2018 at 15:16):

But more generally, if you're looking for theorems that follow a particular pattern, you can try the #find command. e.g.

import tactic.find
#find  (¬ _  false)  _

Wojciech Nawrocki (Sep 04 2018 at 15:16):

Oh, that book looks great, maybe it should also be visible in the "Documentation" section of leanprover.github.io . I'll definitely give it a go! I came across this while trying to prove de morgan both ways, and turns out classical is indeed required :) https://math.stackexchange.com/questions/120187/do-de-morgans-laws-hold-in-propositional-intuitionistic-logic

Johan Commelin (Sep 04 2018 at 15:17):

You can PR that book to the documentation of mathlib, if you want (-;

Wojciech Nawrocki (Sep 04 2018 at 15:56):

How horrible is this proof? :mischievous:

variables p q : Prop

theorem de_morgan_1_a (hnpnq: ¬p  ¬q): ¬(p  q) :=
  assume (hpq: p  q),
  or.elim hnpnq
    (assume hnp: ¬p,
      show false, from hnp hpq.left)
    (assume hnq: ¬q,
      show false, from hnq hpq.right)

-- only provable within classical logic!
theorem de_morgan_1_b (hnpq: ¬(p  q)): ¬p  ¬q :=
  classical.by_contradiction
    (assume not_conclusion: ¬(¬p  ¬q),
      have hpq: p  q, from and.intro
        (show p, from classical.by_contradiction
          (assume hnp: ¬p,
            not_conclusion (show ¬p  ¬q, from or.intro_left (¬q) hnp)))
        (show q, from classical.by_contradiction
          (assume hnq: ¬q,
            not_conclusion (show ¬p  ¬q, from or.intro_right (¬p) hnq))),
      show false, from hnpq hpq)

theorem de_morgan_1: ¬(p  q)  ¬p  ¬q :=
  -- annpoying having to specify p and q
  iff.intro (de_morgan_1_b p q) (de_morgan_1_a p q)

Kenny Lau (Sep 04 2018 at 16:03):

it's alright

Bryan Gin-ge Chen (Sep 04 2018 at 16:05):

In the last theorem, you can use underscores instead of p's and q's if you want.

Kevin Buzzard (Sep 04 2018 at 16:06):

It's so much easier and nicer to do it in tactic mode if you're going to spell it all out like this:

variables p q : Prop

theorem de_morgan_1_a (hnpnq: ¬p  ¬q): ¬(p  q) :=
begin
  intro hpq,
  cases hnpnq with hnp hnq,
  { apply hnp,
    exact hpq.left},
  { apply hnq,
    exact hpq.right}
end

Kevin Buzzard (Sep 04 2018 at 16:06):

You can see where you're going!

Kevin Buzzard (Sep 04 2018 at 16:08):

If you're going to do it in term mode you may as well just do

variables p q : Prop

theorem de_morgan_1_a (hnpnq: ¬p  ¬q): ¬(p  q) :=
λ hpq, or.elim hnpnq (λ hnp, hnp hpq.1) (λ hnq, hnq hpq.2)

Kenny Lau (Sep 04 2018 at 16:09):

yeah but you've already known Lean for a year

Kevin Buzzard (Sep 04 2018 at 16:11):

Kenny can you golf de_morgan_1_b?

Kevin Buzzard (Sep 04 2018 at 16:11):

oh it will already be in mathlib I guess

Wojciech Nawrocki (Sep 04 2018 at 16:15):

Thanks for the feedback! Haven't quite grasped tactics yet, so doing things explicitly for now

Kevin Buzzard (Sep 04 2018 at 16:17):

tactics are the bomb if you're a learner. I don't know why they leave them so late in TPIL.

Kevin Buzzard (Sep 04 2018 at 16:17):

theorem de_morgan_1_a (hnpnq: ¬p  ¬q): ¬(p  q)
| hp, hq := or.elim hnpnq (absurd hp) (absurd hq)

Mathlib's proof.

Kevin Buzzard (Sep 04 2018 at 16:17):

Absolutely terrifying for beginners :-)

Kevin Buzzard (Sep 04 2018 at 16:19):

The theorem is supposed to be constructing a proof of false from a proof of p and q, so the equation compiler matches the proof of p and q with a proof of p and a proof of q and then it's pretty much the same as before.

Kevin Buzzard (Sep 04 2018 at 16:21):

re: specifying p and q. How about this?

variables {p q : Prop} -- trick for making variables implicit

theorem de_morgan_1_a (hnpnq: ¬p  ¬q): ¬(p  q) :=
  assume (hpq: p  q),
  or.elim hnpnq
    (assume hnp: ¬p,
      show false, from hnp hpq.left)
    (assume hnq: ¬q,
      show false, from hnq hpq.right)

-- only provable within classical logic!
theorem de_morgan_1_b (hnpq: ¬(p  q)): ¬p  ¬q :=
  classical.by_contradiction
    (assume not_conclusion: ¬(¬p  ¬q),
      have hpq: p  q, from and.intro
        (show p, from classical.by_contradiction
          (assume hnp: ¬p,
            not_conclusion (show ¬p  ¬q, from or.intro_left (¬q) hnp)))
        (show q, from classical.by_contradiction
          (assume hnq: ¬q,
            not_conclusion (show ¬p  ¬q, from or.intro_right (¬p) hnq))),
      show false, from hnpq hpq)

theorem de_morgan_1: ¬(p  q)  ¬p  ¬q :=
  -- no longer annpoying
  iff.intro (de_morgan_1_b) (de_morgan_1_a)

Wojciech Nawrocki (Sep 04 2018 at 16:29):

Oh, that's nice! I missed that they can be made implicit globally
re: mathlib, i'll just quote TPIL: "Once again, you should exercise judgment as to whether such abbreviations enhance or diminish readability."

Kevin Buzzard (Sep 04 2018 at 16:29):

Instead of assuming classical logic, mathlib (in logic/basic.lean) just assumes decidability of p:

theorem de_morgan_1_b (hnpq: ¬(p  q)) [decidable p] : ¬p  ¬q :=
if hp : p then or.inr (λ hq, hnpq hp, hq) else or.inl hp

Kevin Buzzard (Sep 04 2018 at 16:29):

my impression is that mathlib is not meant to be readable, they are looking for speed and breadth

Wojciech Nawrocki (Sep 04 2018 at 16:41):

Hm, more noob questions, what's the difference between classical logic and "decidable p"? Since LEM states that p is either true or false, isn't that effectively "p is decidable"?

Kevin Buzzard (Sep 04 2018 at 16:42):

Here's a classical proof.

theorem de_morgan_1_b (hnpq: ¬(p  q)) : ¬p  ¬q :=
or.elim (classical.em p) (λ hp, or.inr $ λ hq, hnpq hp, hq) or.inl

Chris Hughes (Sep 04 2018 at 16:42):

Not quite, em means you know p is either true or false, decidable means you know which one.

Kevin Buzzard (Sep 04 2018 at 16:43):

The classical proof gives this:

#print axioms de_morgan_1_b
/-
classical.choice
quot.sound
propext
-/

The decidable proof uses no "maths axioms"

Kevin Buzzard (Sep 04 2018 at 16:44):

As Chris says, assuming decidability is slightly stronger. But to a mathematician like me they're all the same.

Kevin Buzzard (Sep 04 2018 at 16:44):

Furthermore they're all assumable without any worries :-)

Kevin Buzzard (Sep 04 2018 at 16:45):

Johannes Hoelzl once argued that trying to write as small proofs as possible was a good exercise.

zaa (Sep 29 2018 at 20:35):

Hello! Is there some way to use Lean without emacs or VisualStudio? Asking for CoqIde-like editor would be probably too much, but maybe there's some way to use Notepad or command line?

Patrick Massot (Sep 29 2018 at 20:37):

Sure, you can use command line, after editing your file in any editor you like

Kenny Lau (Sep 29 2018 at 20:38):

you can always use any editor to edit the file and then lean --make the file, although you won't be able to interact easilier

Scott Olson (Sep 29 2018 at 20:38):

In case you're not familiar, the Lean reference manual recommends use with Visual Studio Code, which is actually a completely separate IDE from Visual Studio, which is cross platform, simpler, etc. I personally find the experience using Lean in VSCode similar to using CoqIde

Kenny Lau (Sep 29 2018 at 20:38):

(why isn't easilier a word?)

zaa (Sep 29 2018 at 20:40):

Ok, then I will both try Visual Studio Code and get used to lean --make.
Thank you!

Kevin Buzzard (Sep 29 2018 at 20:56):

I'm not sure lean --make will be much fun, but I could imagine it would work. Two other possibilities are the Lean Web Editor, and CoCalc; these are both web-based ways to run Lean. I use unix and am quite anti-MS software in general (and they typically don't target my platform anyway) but actually I've had a very positive experience using VS code in linux. Emacs runs in a terminal window.

zaa (Sep 29 2018 at 21:24):

Lean: Error: Command failed: lean --version 'lean' is not recognized as an internal or external command, operable program or batch file.

Trying to run Lean extension in VSCode. I have added both necessary paths to PATH, but, it seems, i'm missing something else.

Kenny Lau (Sep 29 2018 at 21:30):

maybe you have a space in your path

zaa (Sep 29 2018 at 21:41):

It's working now, yay. I just closed and reopened VSCode.

Chris Hughes (Sep 29 2018 at 22:08):

(why isn't easilier a word?)

I think it's because it's an adverb not an adjective. Off the top of my head, I can't think of any English adverbs that can be suffixed with -er.

zaa (Sep 30 2018 at 10:58):

Does Lean have a tactic similar to Omega in coq?

Kevin Buzzard (Sep 30 2018 at 11:01):

I believe the answer is "not yet". I know nothing about Coq but I've heard people talk about Omega. Can you briefly describe what it does? Another noob question :-)

Kevin Buzzard (Sep 30 2018 at 11:02):

We have linarith and cc.

Mario Carneiro (Sep 30 2018 at 11:05):

I think omega is cooper

zaa (Sep 30 2018 at 11:07):

It solves goals in Presburger arithmetic. Equalities containing only addition and substraction (and multiplication by constant, ofc).

For example: 8n = 4m+3 -> False

Mario Carneiro (Sep 30 2018 at 11:09):

what do you use it for? is it just divisibility goals like that one?

zaa (Sep 30 2018 at 11:11):

Oh, it seems to work with inequalities too. Will test on Coq a bit, as I have already forgotten things.

Mario Carneiro (Sep 30 2018 at 11:13):

no, my question is when do you think "I should use omega"

Mario Carneiro (Sep 30 2018 at 11:14):

I know about presburger arithmetic but I think it's probably a bit too wide a target - I doubt people really need the crazy quantifier complexity part

zaa (Sep 30 2018 at 11:17):

https://coq.inria.fr/refman/addendum/omega.html - found the documentation.
There's an example:
z > 0 -> 2 * z + 1 > z

As far as i can remember, I mostly used it for goals like
[inequality/equality] -> [another one] -> x = something
or A <= x <= B
or maybe False

Mario Carneiro (Sep 30 2018 at 11:18):

cooper is a tactic for presburger arithmetic written in lean by Seul Baek, but I don't think it is ready for production

Kevin Buzzard (Sep 30 2018 at 12:12):

https://coq.inria.fr/refman/addendum/omega.html - found the documentation.

Oh thank you! I know nothing about Coq or where to look for this stuff.

zaa (Sep 30 2018 at 21:36):

Yes, that's the website where it lives. I had fun with Coq for some time but paused it some year ago (will return to it soon, probably simultaneously to more serious lean learning).

zaa (Sep 30 2018 at 21:51):

Next noob question:
Is there some simple example/tutorial of quotient types - how to define and use them?

Reid Barton (Sep 30 2018 at 22:01):

There is a section in TPIL: https://leanprover.github.io/theorem_proving_in_lean/axioms_and_computation.html#quotients

Reid Barton (Sep 30 2018 at 22:05):

For a real-world example you can take a look at linear_algebra.quotient_module

zaa (Sep 30 2018 at 22:06):

Thank you!

Kevin Buzzard (Sep 30 2018 at 23:00):

https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/teaching.20use.20of.20quotients.20in.20Lean

Kevin Buzzard (Sep 30 2018 at 23:01):

I wrote https://github.com/kbuzzard/xena/blob/master/xenalib/m1f/zmod37.lean specifically to help some of my students to learn about using quotients in Lean.

Wojciech Nawrocki (Oct 24 2018 at 18:40):

Using my old thread for more noob questions:
Can I use something like cases but without stating the hypothesis name? Namely, I'd like a tactic that splits conjunctions into two hypotheses and disjunctions into two goals. More generally, how does one go about searching for tactics that do something?

Johan Commelin (Oct 24 2018 at 18:44):

split will split goals.

Wojciech Nawrocki (Oct 24 2018 at 18:45):

Yep, sorry I should've specified - I want to split hypotheses.

Johan Commelin (Oct 24 2018 at 18:45):

Like have h1 := h.left, have h2 := h.right?

Johan Commelin (Oct 24 2018 at 18:46):

And now you want to do that automatically for all hypotheses, recursively?

Reid Barton (Oct 24 2018 at 18:46):

cases does both of those things already, so I guess you mean something that applies cases automatically?

Wojciech Nawrocki (Oct 24 2018 at 18:46):

Yep, that would be for ANDs, but without stating what the name is, and also do it for ORs (in which case two or more goals would appear). Yep, automatically and recursively.

Reid Barton (Oct 24 2018 at 18:47):

I think the answer to the more general question is "read through https://github.com/leanprover/mathlib/blob/master/docs/tactics.md, and then look through tactic.interactive in mathlib and more generally the rest of tactic.* to find more things"

Reid Barton (Oct 24 2018 at 18:48):

tidy does things like this; it tries a bunch of different tactics in a loop, one of which is auto_cases

Wojciech Nawrocki (Oct 24 2018 at 18:51):

That looks about right, thanks!

Rob Lewis (Oct 24 2018 at 18:55):

safe will do this, and a bit more. I think it should be less aggressive than tidy.

Wojciech Nawrocki (Oct 24 2018 at 19:25):

Oh damn, it just solves everything by itself O.o

Keeley Hoek (Oct 26 2018 at 07:54):

c.f. auto_cases

Wojciech Nawrocki (Nov 03 2018 at 01:35):

More questions!
What's the syntax for matching on inductive constructors by name? E.g. for list, something like Nil => 0, Cons(hd, tl) => 1 + (len tl) would be a Rust way to define len recursively

Bryan Gin-ge Chen (Nov 03 2018 at 01:56):

Do you mean something like this?

def len : list α  
| list.nil := 0
| (list.cons a b) := 1 + len b

Wojciech Nawrocki (Nov 03 2018 at 02:00):

Yep that's it - thanks!

Wojciech Nawrocki (Nov 03 2018 at 17:16):

Ignore me, mixed up my languages.

Wojciech Nawrocki (Nov 03 2018 at 18:37):

Is there any reason why fin and multiset don't support the {1, 2, 3} notation that set does? What's the best way to construct concrete finsets?

Johan Commelin (Nov 03 2018 at 18:38):

Do you want a type or a set?

Chris Hughes (Nov 03 2018 at 18:40):

You need decidable_eq α to use that notation for finset α.

Chris Hughes (Nov 03 2018 at 18:41):

For multisets this works for me without any decidability assumptions

example {α : Type*} (a b c : α) : multiset α := {a,b,c}

Wojciech Nawrocki (Nov 03 2018 at 18:42):

@Johan Commelin a concrete set, say {v} for some given v: \a
@Chris Hughes ah indeed, why does set not require it then?

Chris Hughes (Nov 03 2018 at 18:45):

They notation is for has_insert.insert
For sets insert a s := {b : α | b = a ∨ b ∈ s}, and there's no decidable equality required.

For finsets, there has to be an underlying list with no duplicates, so it has to check whether a is already in the set, which requires decidable_eq

Wojciech Nawrocki (Nov 03 2018 at 19:33):

Then given a singleton set, how can I extract the element? I tried folding it into a list to grab the first element, but fold requires commutativity and list.append is not commutative.

Chris Hughes (Nov 03 2018 at 19:40):

Do you have a proof that it's a singleton? I think there's a PR about finite unique computable choice.

Wojciech Nawrocki (Nov 03 2018 at 19:42):

Yeah, i'm grabbing it under the assumption that card vals = 1.

Chris Hughes (Nov 03 2018 at 19:50):

do you need it to be computable? You can use finset.exists_mem_of_ne_empty if you don't. Do you need the fact that everything in the singleton is equal?

Wojciech Nawrocki (Nov 03 2018 at 20:09):

I think exists_mem_of_ne_empty will work. thx!

Wojciech Nawrocki (Nov 03 2018 at 20:29):

So now i'm seeing a really strange error when trying to decompose the Exists:

constant α: Type
constant a: α
constant as: finset α
#check a  as -- Prop
constant ex :  (a : α), a  as
def test := match ex with a, b := -- induction tactic failed, recursor 'Exists.dcases_on' can only eliminate into Prop
  0
end

Kevin Buzzard (Nov 03 2018 at 21:04):

The recursor only eliminates into prop and your goal is a type

Kevin Buzzard (Nov 03 2018 at 21:04):

so the recursor cannot be applied

Wojciech Nawrocki (Nov 03 2018 at 21:05):

Yep, I just realised this. Basically, i'm trying to extract a concrete value of the type \a from a proof of existence. But I guess this could only work in purely constructionist logic?

Kevin Buzzard (Nov 03 2018 at 21:06):

There are tools in the classical namespace which should let you do this

Kevin Buzzard (Nov 03 2018 at 21:07):

You shouldn't use constants by the way, you should use variables -- they work a bit better and there's less risk

Wojciech Nawrocki (Nov 03 2018 at 21:08):

Oh yeah, that was just to make the example code short

Chris Hughes (Nov 03 2018 at 21:09):

It should be possible to define the function you want constructively, but it hasn't been done yet.

Kevin Buzzard (Nov 03 2018 at 21:10):

import data.finset
variable {α: Type}
variable {a: α}
variable {as: finset α}
#check a  as -- Prop
variable ex :  (a : α), a  as
noncomputable def test : α := classical.some ex

Kevin Buzzard (Nov 03 2018 at 21:11):

Right -- this noncomputable approach works for any existence statement. But I now understand that in the specific case of finsets you might be able to do better.

Bryan Gin-ge Chen (Nov 03 2018 at 21:11):

This is the relevant PR, right?

Kevin Buzzard (Nov 03 2018 at 21:12):

import data.finset

variables {α : Type} {a : α} {as : finset α} (ex :  (a : α), a  as)

noncomputable def test : α := classical.some ex

Shorter and no constants ;-)

Wojciech Nawrocki (Nov 03 2018 at 21:17):

Also works with constants, but fair enough :)
Anyhow, I need it to be computable because I want to extract concrete elements from concrete sets and do things with them

Kenny Lau (Nov 03 2018 at 21:39):

something that almost works:

Kenny Lau (Nov 03 2018 at 21:39):

import data.finset

lemma list.perm_singleton {α : Type*} {L : list α} {x : α} (H : L ~ [x]) : L = [x] :=
begin
  generalize_hyp hs : [x] = S at H ,
  induction H,
  case list.perm.nil { refl },
  case list.perm.skip : y L₁ L₂ H ih {
    cases hs, cases list.perm_nil.1 H, refl
  },
  case list.perm.swap { injections },
  case list.perm.trans : L₁ L₂ L₃ H12 H23 ih1 ih2 {
    cases hs, cases ih2 rfl, cases ih1 rfl, refl
  }
end

def extract {α : Type*} (s : finset α) (hs : s.card = 1) : α :=
finset.rec_on s
  (λ m, quotient.hrec_on m
    (λ L _, list.cases_on L
      (assume hcard : 0 = 1, absurd hcard dec_trivial)
      (λ hd tl hcard, hd))
    (λ L₁ L₂ HL, function.hfunext (congr_arg _ $ quotient.sound HL) $
    λ hnd1 hnd2 hheq, begin
  cases L₂,
  case list.nil { cases list.perm_nil.1 HL, refl },
  case list.cons : hd₂ tl₂ {
    cases L₁,
    case list.nil { cases list.perm_nil.1 (list.perm.symm HL) },
    case list.cons : hd₁ tl₁ {
      apply function.hfunext,
      { simp only [finset.card_def, multiset.card],
        rw quotient.sound HL },
      intros hcard₁ hcard₂ hheq,
      cases multiset.card_eq_one.1 hcard₁ with x₁ hx₁,
      cases multiset.card_eq_one.1 hcard₂ with x₂ hx₂,
      cases list.perm_singleton (quotient.exact hx₁),
      cases list.perm_singleton (quotient.exact hx₂),
      cases list.perm_singleton HL,
      refl
    }
  }
end)) hs

Kenny Lau (Nov 03 2018 at 21:39):

@Chris Hughes can you fix this?

Chris Hughes (Nov 03 2018 at 21:49):

example {α : Type*} (s : finset α) : s.card = 1  {a : α // s = finset.singleton a} :=
finset.rec_on s (λ s, @quotient.rec_on_subsingleton _ _
  (λ t : multiset α, Π (nodup : multiset.nodup t),
    finset.card {val := t, nodup := nodup} = 1  {a // finset.mk t nodup = finset.singleton a})
      (λ l, ⟨λ a b, funext (λ x, funext (λ y, subtype.eq $ finset.singleton_inj.1 $
        by rw [ (a x y).2,  (b x y).2]))) s
  (λ l, list.rec_on l (λ _ h, nat.no_confusion h)
    (λ a l _ _ h, have l.length = 0, from nat.succ_inj h,
      a, finset.eq_of_veq $ by dsimp; rw [list.length_eq_zero.1 this]; refl)) )

Chris Hughes (Nov 03 2018 at 21:50):

Not very pretty

Kenny Lau (Nov 03 2018 at 21:50):

import data.finset

lemma list.perm_singleton {α : Type*} {L : list α} {x : α} (H : L ~ [x]) : L = [x] :=
begin
  generalize_hyp hs : [x] = S at H ,
  induction H,
  case list.perm.nil { refl },
  case list.perm.skip : y L₁ L₂ H ih {
    cases hs, cases list.perm_nil.1 H, refl
  },
  case list.perm.swap { injections },
  case list.perm.trans : L₁ L₂ L₃ H12 H23 ih1 ih2 {
    cases hs, cases ih2 rfl, cases ih1 rfl, refl
  }
end

def extract {α : Type*} (s : finset α) (hs : s.card = 1) : α :=
finset.rec_on s
  (λ m, quotient.rec_on m
    (λ L _, show L.length = 1  α, from list.cases_on L
      (λ H, absurd H dec_trivial)
      (λ hd tl H, hd))
    (λ L₁ L₂ HL, begin
  ext H1 H2, rcases list.length_eq_one.1 H2 with x₂, rfl,
  cases list.perm_singleton HL, refl
end)) hs

my version

Kenny Lau (Nov 03 2018 at 21:50):

well yours is much shorter

Kenny Lau (Nov 03 2018 at 21:50):

clever use of subsingleton...

Kenny Lau (Nov 03 2018 at 21:52):

theorem extract_mem {α : Type*} (s : finset α) (hs : s.card = 1) :
  extract s hs  s :=
begin
  induction s with m _,
  rcases m with L,
  cases L with hd tl, { cases hs },
  left, refl
end

Kenny Lau (Nov 03 2018 at 21:53):

@Wojciech Nawrocki so we have 2 solutions now

Kenny Lau (Nov 03 2018 at 21:53):

(i.e. mine and Chris's solution)

Wojciech Nawrocki (Nov 03 2018 at 21:55):

Oh wow, these are quite complex! I wonder if i should have just used lists instead :P but thanks a lot

Kenny Lau (Nov 06 2018 at 01:37):

related: https://github.com/leanprover/mathlib/pull/421

Wojciech Nawrocki (Nov 09 2018 at 13:16):

When a goal contains a reducible definition, how can i expand it to work with the internals? Namely, in here:

  @[reducible]
  def compose_partial (f₁: α  option β) (f₂: β  option γ)
    : α  option γ :=
  (λ a: α, option.cases_on (f₁ a) none (λ x, f₂ x))

  notation [parsing_only] a `⬝` b := compose_partial b a

  theorem compose_none (f₁: α  option β) (f₂: β  option γ) (x: α) (h: f₁ x = none)
    : (f₂  f₁) x = none :=
  begin
    sorry
  end

I would like to expand compose_partial to carry through the none and get back a none.

Rob Lewis (Nov 09 2018 at 13:22):

You can use unfold compose_partial. simp [compose_partial] or dsimp [compose_partial] can also be useful.

Wojciech Nawrocki (Nov 09 2018 at 13:23):

Ah, unfold. Thanks!

Kenny Lau (Nov 09 2018 at 14:32):

@[reducible] means that the typeclass system will automatically unfold it

Kenny Lau (Nov 09 2018 at 14:32):

but only the typeclass system

Wojciech Nawrocki (Nov 17 2018 at 20:09):

How can I make an instance of a dependent product (x, p x) where p is some proposition depending on x? Lean complains about impredicativity:

type mismatch at application
  (n, h)
term
  h
has type
  n = 4 : Prop
but is expected to have type
  ?m_1 : Type ?

Chris Hughes (Nov 17 2018 at 20:10):

use subtype

Chris Hughes (Nov 17 2018 at 20:11):

If you're using prod, it won't work because it's non dependent and it doesn't accept Propositions.

Reid Barton (Nov 17 2018 at 20:11):

Parentheses are only for prod, yeah

Wojciech Nawrocki (Nov 17 2018 at 20:20):

Oh I see, thanks!

Kenny Lau (Nov 17 2018 at 20:27):

prod is non-dependent sigma

Kenny Lau (Nov 17 2018 at 20:27):

but if it's proposition then you're better off using subtype which is a sort of specialize sigma

Wojciech Nawrocki (Nov 18 2018 at 21:56):

Given an inductive type with some variants that take arguments, e.g.

inductive Foo: Type
| A : nat -> Foo
| B: Foo

Is there a better way of saying that a particular x: Foo was constructed by A regardless of what the argument was than \ex n: nat, x = A n?

Kevin Buzzard (Nov 18 2018 at 22:15):

I don't think so. "x was constructed by A and I don't know what the argument was" is exactly \ex n: nat, x = A n, right? What's wrong with this way of saying it?

Chris Hughes (Nov 18 2018 at 22:19):

Other approaches

def p : foo  Prop
| (A n) := true
| B     := false

inductive p : foo  Prop
| bar : p (A n)

Kevin Buzzard (Nov 18 2018 at 22:21):

That first one is a much better way :-) I don't understand the second one!

Wojciech Nawrocki (Nov 18 2018 at 22:22):

Hm, I guess it might just be nice to have a shorthand like p in Chris's example for when the constructor is unwieldy, e.g. has lots of arguments. p would sound better as e.g. is_A

Rob Lewis (Nov 18 2018 at 22:22):

The second one is an inductive proposition. I think you need inductive instead of def. This seems like the "canonical" way to me, and you can easily prove it equivalent to one using exists.

Chris Hughes (Nov 18 2018 at 22:25):

The inductive one gives you a nice recursor.

Bryan Gin-ge Chen (Nov 18 2018 at 22:42):

Is there another typo in the second one? I'm trying to figure out how to use it and I'm getting unknown identifier 'n'

Rob Lewis (Nov 18 2018 at 22:48):

It should look like

inductive Foo : Type
| A : nat -> Foo
| B: Foo

inductive Foo.is_A : Foo  Prop
| of_A (n) : Foo.is_A (Foo.A n)

Rob Lewis (Nov 18 2018 at 22:49):

The idea being, Foo.is_A is a family of propositions. For any n : nat, Foo.is_A.of_A n is a proof of Foo.is_A (Foo.A n).

Bryan Gin-ge Chen (Nov 18 2018 at 22:51):

Thanks! I'd tried adding n after bar and I forgot that the parentheses were necessary.


Last updated: Dec 20 2023 at 11:08 UTC