## Stream: general

#### Peter Nelson (Feb 19 2021 at 22:27):

I am working with a bunch of calculations with expressions that depend on fintype, and mismatch issues are happening. From what I understand, avoiding the mismatches arising is not feasible, but I'm looking for a non-painful way to handle them.

Each individual mismatch can generally be handled with convert rfl, and indeed sometimes this will kill the problems if there is more than one. But it can be hard to handle these issues when they occur in a complicated context and the pretty-printer makes differences invisible. For instance, suppose that a and a' are complicated expressions in int, indistinguishable without diving into implicit parameters, and hiding different fintype instances. Let b and b' be another such pair. Now a = a' and b = b' can be proved with convert rfl (or maybe congr'), but how would I prove, say, that -b + x + a + b' + y + z - a' = x + y + z, where x, y and z are themselves long and complicated enough that copy-pasting them into a proof would double its length?

This is clearly possible, but quite awkard in the middle of a proof. Of course, a proof somehow isomorphic to rw [(by convert rfl : a = a'), (by convert rfl : b = b')], linarith is what I would like. But I can't do this without hundreds of characters and underscores, because a and a' are syntactically identical!

Unfortunately it is hard to come up with an mwe because the nature of my gripe is 'in a complicated context', but I hope I've communicated my question.

(Of course, what I would really like is a way to seamlessly replace fintype with a similar typeclass that is purely propositional, in a way that doesn't involve remaking half the API from scratch, but I don't know how to do that, either).

#### Eric Wieser (Feb 20 2021 at 00:50):

If you can't rewrite with a lemma due to a mismatching fintypes instance, that usually means that the lemma is written badly, and only applies to a specific instance

#### Kevin Buzzard (Feb 20 2021 at 00:57):

I teach my mathematician students to use set.finite and [finite X] where none of these problems occur. I have no interest in constructive finiteness

#### Kevin Buzzard (Feb 20 2021 at 01:04):

oh apparently mathlib doesn't have finite X -- hard luck.

#### Johan Commelin (Feb 20 2021 at 07:14):

@Peter Nelson These issues sound quite similar to the issues that we have been facing in homological algebra. Where you have a complex of (say) vector spaces, indexed by int or nat. And now you fact the issues that V i is not the same vector space as V (i - 1 + 1). Which is of course ridiculous. We are still experimenting to find the best solution.

#### Johan Commelin (Feb 20 2021 at 07:15):

But more on topic, I think that you provide another strong datapoint for the need of a propositional analogue of fintype.

#### Kevin Buzzard (Feb 20 2021 at 15:12):

@Peter Nelson let's first get one thing clear -- are we talking about finite types, or finite subsets of types? We already have set.finite in mathlib, which is an "I am finite" predicate on a set which does not suffer from all the constructivist problems you're seeing.

#### Peter Nelson (Feb 20 2021 at 15:21):

We're talking about finite types. I'm not using finset directly at all, except where I'm being forced to. Here is some code - one of the problems occurs in the last lemma.

(Related to the fact that I'm not using finset, what I'm trying to do here is to make the shorthand ∑ (a : X), f a easier to work with, since most of the finset.sum API is instead written in terms of ∑ a in X, f a.)

import tactic
----------------------------------------------------------------
open_locale classical big_operators
open set

variables {α β: Type}[fintype α][add_comm_monoid β](f : α  β)

lemma set.to_finset_insert' (X : set α)(e : α) :
(X  {e}).to_finset = X.to_finset  {e} :=
by {ext, simp[or_comm]}

lemma fin_sum_eq (X : set α):
(a : X), f a =  a in X.to_finset, f a :=
let φ : X  α := coe, subtype.coe_injective in (finset.sum_map (finset.univ) φ f).symm

lemma fin_sum_insert {X : set α}{e : α}:
e  X   (a : X  {e}), f a = ( (a : X), f a) + f e :=
begin
rintro he,
have hdj :disjoint X.to_finset {e},
{ rw [finset.disjoint_iff_inter_eq_empty], ext,
simp only [finset.not_mem_empty, not_and, finset.mem_singleton, iff_false, finset.mem_inter, mem_to_finset],
exact λ haX hae, false.elim (he (by {rwa hae})),},

-- this next claim causes instance mismatch problems if fin_sum_eq is invoked directly,
-- due to two competing instances of fintype for X ∪ {e}
have hXe :  (a : (X {e}) ), f a =  a in (X  {e}).to_finset, f a,
convert fin_sum_eq f (X  {e} : set α),

rw [hXe, fin_sum_eq f (X : set α), set.to_finset_insert' X e, finset.sum_union hdj],
simp,
end

#### Mario Carneiro (Feb 20 2021 at 15:28):

Why don't you just use finsets here? it shouldn't be hard to have analogues of all the sets you could want with open_locale classical

#### Peter Nelson (Feb 20 2021 at 15:33):

The set API is just more complete.

#### Mario Carneiro (Feb 20 2021 at 15:36):

Only when it comes to equality of sets. The finset API is a lot more complete when it comes to summation; you can do the summation stuff on finsets and pull back to sets for the set algebra

#### Mario Carneiro (Feb 20 2021 at 15:44):

lemma fin_sum_insert {X : set α}{e : α}:
e  X   (a : X  {e}), f a = ( (a : X), f a) + f e :=
begin
rintro he,
obtain X, rfl := (finite.of_fintype X).exists_finset_coe,
convert (fin_sum_eq f _).trans _,
{ congr', ext, simp },
simpa using he,
end

#### Mario Carneiro (Feb 20 2021 at 15:46):

set.to_finset doesn't seem to have many lemmas about it, although it does have mem_to_finset which is why the ext, simp works

#### Peter Nelson (Feb 20 2021 at 15:46):

so the trick is exists_finset_coe?

#### Mario Carneiro (Feb 20 2021 at 15:47):

That's how you make everything use finsets

#### Peter Nelson (Feb 20 2021 at 15:48):

Good to know - thanks!

#### Peter Nelson (Feb 20 2021 at 16:09):

Unfortunately it seems like the problem cascades. Here's an attempted consequence of the above where a mismatch issue carries forward, with either of our proofs of fin_sum_insert. The context is a little contrived - is is the problematic part of a proof by induction. The proof that works involves reducing to a case where a single convert resolves the goal, but rewriting earlier fails.

def subadditive (g : set α  ) :=
X Y, g (X  Y)  g X + g Y

lemma foo (S : set (set α)){g : set α  }{X₀ : set α}(hX₀ : X₀  S)
(hg : subadditive g) (hS : g (⋃₀ S)   (X : S), g X):
g (⋃₀(S  {X₀}))   (X : (S  {X₀})), g X :=
begin
-- rw fin_sum_insert g hX₀,
-- Doesn't work

simp_rw [sUnion_union, sUnion_singleton] at hS ,

refine le_trans (hg _ _) _,
convert (fin_sum_insert g hX₀).symm,
-- works
end

#### Johan Commelin (Feb 20 2021 at 16:11):

So you can't use S : finset (set \a)?

#### Peter Nelson (Feb 20 2021 at 16:13):

I probably could, but I would be worried that this will just move the problem further upwards. In the case I want to invoke, S has type set (set \a) because it's a collection of equivalence classes, so I would have to use some type of equivalence between set and finset to get to finset (set \a).

#### Mario Carneiro (Feb 20 2021 at 16:22):

Yes, that's exists_finset_coe as you saw

or set.to_finset

#### Johan Commelin (Feb 20 2021 at 16:25):

So I guess you can do

obtain \<S, rfl\> := exists_finset_coe S

or something like that, as first line of the proof

#### Johan Commelin (Feb 20 2021 at 16:25):

Right, as Mario suggested upstairs:

obtain X, rfl := (finite.of_fintype X).exists_finset_coe,

#### Johan Commelin (Feb 20 2021 at 16:26):

After that, the proof should be "smooth"

#### Mario Carneiro (Feb 20 2021 at 16:26):

it wasn't completely smooth, there seem to be some missing simp lemmas

#### Peter Nelson (Feb 20 2021 at 16:38):

Yeah, that last proof is something where I want things from both APIs at the same time.

#### Peter Nelson (Feb 20 2021 at 16:44):

of course, what I actually want is that fintype be propositional.

#### Eric Wieser (Feb 20 2021 at 18:31):

If you use convert ... using 1, does it show what doesn't match?

#### Peter Nelson (Feb 20 2021 at 20:02):

The first instance of fintype ↥(S ∪ {X₀}) is this :

(@subtype.fintype (set α) (λ (x : set α), x  S)
(@set.decidable_mem (set α) S (λ (a : set α), classical.prop_decidable (S a)))
(@set.fintype α _inst_1))
(@set.fintype_pure (set α) X₀)

and the second is this :

@set.fintype_union (set α)
(λ (a b : set α),
@fintype.decidable_pi_fintype α (λ (a : α), Prop) (λ (a : α) (a b : Prop), classical.prop_decidable (a = b))
_inst_1
a
b)
S
{X₀}
(@subtype.fintype (set α) (λ (x : set α), x  S)
(λ (a : set α), @set.decidable_mem (set α) S (λ (a : set α), classical.prop_decidable (S a)) a)
(@set.fintype α _inst_1))
(@set.fintype_pure (set α) X₀)

#### Peter Nelson (Feb 20 2021 at 20:07):

Ah, so it's actually decidable_eq that is the culprit! The difference between the above is :

fintype.decidable_pi_fintype α (λ (a : α), Prop) (λ (a : α) (a b : Prop), classical.prop_decidable (a = b))
_inst_1
a
b

vs

classical.prop_decidable (a = b)

I don't know if that makes any of these problems easier to address....

#### Kevin Buzzard (Feb 20 2021 at 21:14):

What should propositional finiteness be called? [is_finite alpha]?

#### Eric Wieser (Feb 20 2021 at 22:20):

My assumption is that docs#fin_sum_insert is stated poorly

#### Eric Wieser (Feb 20 2021 at 22:20):

But that link doesn't work - where is that lemma?

#### Eric Wieser (Feb 20 2021 at 22:32):

Is there a full mwe?

#### Eric Wieser (Feb 20 2021 at 22:35):

I think the lemma needs [fintype X] and [fintype (X \union {e})] to avoid this problem

#### Peter Nelson (Feb 20 2021 at 22:55):

This mwe is a union of things earlier, but here is all of it in one place:

import tactic
----------------------------------------------------------------
open_locale classical big_operators
open set

variables {α β: Type}[fintype α][add_comm_monoid β](f : α  β)

lemma set.to_finset_insert' (X : set α)(e : α) :
(X  {e}).to_finset = X.to_finset  {e} :=
by {ext, simp[or_comm]}

lemma fin_sum_eq (X : set α):
(a : X), f a =  a in X.to_finset, f a :=
let φ : X  α := coe, subtype.coe_injective in (finset.sum_map (finset.univ) φ f).symm

lemma fin_sum_insert {X : set α}{e : α}:
e  X   (a : X  {e}), f a = ( (a : X), f a) + f e :=
begin
rintro he,
obtain X, rfl := (finite.of_fintype X).exists_finset_coe,
convert (fin_sum_eq f _).trans _,
{ congr', ext, simp },
simpa using he,
end

def subadditive (g : set α  ) :=
X Y, g (X  Y)  g X + g Y

lemma foo (S : set (set α)){g : set α  }{X₀ : set α}(hX₀ : X₀  S)
(hg : subadditive g) (hS : g (⋃₀ S)   (X : S), g X):
g (⋃₀(S  {X₀}))   (X : (S  {X₀})), g X :=
begin
simp_rw [sUnion_union, sUnion_singleton] at hS ,

--would like to rw here with fin_sum_insert but can't.

refine le_trans (hg _ _) _,
convert (fin_sum_insert g hX₀).symm,
end

#### Eric Wieser (Feb 20 2021 at 22:58):

Thanks, I'll try my idea out myself tomorrow

#### Yakov Pechersky (Feb 21 2021 at 01:10):

Is this just not going to work because subadditive is defined in a classical context?

#### Eric Wieser (Feb 21 2021 at 14:36):

Eric Wieser said:

I think the lemma needs [fintype X] and [fintype (X \union {e})] to avoid this problem

Yes, this fixes it, in conjuction with removing fintype α:

import tactic
----------------------------------------------------------------
open_locale classical big_operators
open set

variables {α β: Type} [add_comm_monoid β](f : α  β)

lemma set.to_finset_insert' (X : set α) (e : α) [fintype X] [fintype (X  {e})]:
(X  {e}).to_finset = X.to_finset  {e} :=
by {ext, simp[or_comm]}

lemma fin_sum_eq (X : set α) [fintype X] :
(a : X), f a =  a in X.to_finset, f a :=
let φ : X  α := coe, subtype.coe_injective in (finset.sum_map (finset.univ) φ f).symm

lemma fin_sum_insert {X : set α}{e : α} [fintype X] [fintype (X  {e})]:
e  X   (a : X  {e}), f a = ( (a : X), f a) + f e :=
begin
rintro he,
unfreezingI { obtain X', rfl := finite.exists_finset_coe ⟨‹fintype X›⟩ },
{ congr', ext, simp },
simpa using he,
end

def subadditive (g : set α  ) :=
X Y, g (X  Y)  g X + g Y

lemma foo (S : set (set α)) [fintype S] {g : set α  } {X₀ : set α} [fintype (S  {X₀})] (hX₀ : X₀  S)
(hg : subadditive g) (hS : g (⋃₀ S)   (X : S), g X):
g (⋃₀(S  {X₀}))   (X : (S  {X₀})), g X :=
begin
simp_rw [sUnion_union, sUnion_singleton] at hS ,
rw fin_sum_insert _ hX₀,  -- rw works
sorry,
end

#### Eric Wieser (Feb 21 2021 at 14:37):

You should never assume a more general fintype instance than the one the lemma actually requires and let the specific one be derived, because then the lemma won't match again terms which obtain the specific one via a different means

#### Peter Nelson (Feb 21 2021 at 19:23):

Thank you! What if I want to invoke fin_sum_insert in the middle of a larger proof where there is already a fintype α instance hanging around?

#### Eric Wieser (Feb 21 2021 at 19:38):

It should work fine

#### Eric Wieser (Feb 21 2021 at 19:40):

When you rewrite, the instances on the left-hand side of the eq / iff will already be present in the goal, while typeclass instances will try to deduce the ones on the right-hand-side

#### Peter Nelson (Feb 21 2021 at 19:52):

Ok. I've run into a curiosity that results from this solution when I'm applying it in an inductive proof. The below is the smallest example where I can reproduce the issue.

import tactic
----------------------------------------------------------------
open_locale classical big_operators
open set

variables {α β : Type}[add_comm_monoid β]

lemma fin_sum_empty (f : α  β) :
(a : ( : set α)), f a = 0 :=
finset.sum_empty

lemma fin_sum_eq (f : α  β)(X : set α)[fintype X]:
(a : X), f a =  a in X.to_finset, f a :=
let φ : X  α := coe, subtype.coe_injective in (finset.sum_map (finset.univ) φ f).symm

lemma fin_sum_insert (f : α  β){X : set α}{e : α}(he : e  X)[fintype X][fintype (X  {e})]:
(a : X  {e}), f a = ( (a : X), f a) + f e :=
begin
unfreezingI {obtain X', rfl := finite.exists_finset_coe ⟨‹fintype X›⟩ },
{ congr', ext, simp },
simpa using he,
end

lemma induction_foo [fintype α](P : set α  Prop):
(P )  ( (X : set α)(e : α), e  X  P X  P (X  {e}))  ( X, P X) :=
sorry

lemma fin_sum_one_eq_card [fintype α](X : set α):
(a : X), (1 : α  ) a = X.to_finset.card :=
begin
revert X, apply induction_foo,
{rw [to_finset_card, empty_card'], convert fin_sum_empty _, },

intros X e he hX,
-- rw fin_sum_insert _ he,
-- doesn't work

rw fin_sum_insert, swap, assumption,
--works

sorry,
end

In the proof of fin_sum_one_eq_card, I am able to rw with fin_sum_insert if I don't pass it the term he, but if I pass it he, the rewrite fails, even though he is exactly the term it needs, and resolving the goal later using he works fine . The swap, assumption handles this cleanly enough in practice, but I'd still like to understand what is happening, and can't figure it out.

#### Kevin Buzzard (Feb 21 2021 at 20:03):

I don't know the answer to your question, but convert works so it's some type class inference issue again. Independent of that, why have you got such a horrible ∑ (a : ↥X), 1 ↑a term? Why not just some over a \in X? Oh! Because it's not a finset :-( I think your fabulous questions are just indicating that we need some API. We solved this with finsum_in when we were doing finite groups: see here.

#### Kevin Buzzard (Feb 21 2021 at 20:05):

I totally agree with you, all this constructive stuff is hard to work with but as you can see there are now sufficiently many experts around going "no it's fine, just think about it this way and there's a trick" that we've all just got used to it and learnt the tricks. Why not just write your own API and sorry it all out? finsum_in will solve all your problems. The proofs are just hacks to reduce everything to finset.sum and are very ugly but you don't care about those, you just reap the benefits.

#### Kevin Buzzard (Feb 21 2021 at 20:15):

@Peter Nelson I hesitated to introduce these new definitions because some people pointed out to me that the tools we have are enough for the job as long as you continually jump over the traps you're running into, and hence because such a nonconstructive approach is not strictly necessary (it all _can_ be done with what we have) I was just in danger of adding to the noise a la xkcd#927. However your situation I think just makes it clear that we need them. If this sort of stuff is deterring beginners then it's clear that there's an argument for it. I've suggested these before but here we go again:

class is_finite (X : Type u) : Prop
noncomputable def finsum {ι M} [add_comm_monoid M] (f : ι  M) : M -- zero if support infinite
noncomputable def finsum_in {ι M} [add_comm_monoid M] (s : set ι) (f : ι  M) : M -- zero if support intersect s is infinite
def fincard (X : Type u) :  -- zero if X is infinite

Why don't you switch to these, sorry all the lemmas you need and feed them back, and we can just make the API? I've done it once before and it was quite fun, I just didn't get round to PR'ing it because some people weren't convinced this stuff was needed. In some sense they might be right -- jump through some hoops, use convert and woo-hoo, it's all computable! I am losing my patience with this approach.

#### Kevin Buzzard (Feb 21 2021 at 20:17):

intros X e he hX,
convert fin_sum_insert _ he, -- this works
have : ((X  {e}).to_finset.card) =  (a : X), (1 : α  ) a + (1 : α  ) e, -- the goal!
sorry,
exact this, -- stupid typeclass fail

#### Kevin Buzzard (Feb 21 2021 at 20:18):

With my approach there will be no up-arrows

#### Jason KY. (Feb 21 2021 at 21:06):

I wonder if it is worthwhile just pr finsum. All of the APIs are already done. I don't think too many standards is an issue if we can easily convert between the standards and I feel that this has come up often enough to warrant a separate definition.

#### Peter Nelson (Feb 21 2021 at 21:47):

I like this idea. I do see the perspective of the more constructively inclined, and am even (on some level) enjoying how much these subtle issues teach me about the language. I'm grateful for all the help, patience and expertise I've been getting here.

However, I am planning to give a talk in the near future to fellows combinatorialists about how great/fun formalization is, and these types of problems are among the downsides on my mind. 'Traps' is the right word - none of the problems are insurmountable, but they are barriers to entry. Being someone very interested in theorems about finite structures, I suspect that this stuff happens more frequently for me than many others, and it would be good to have a solution that can be explained in terms an average mathematician can immediately understand.

Regarding an API, I would love to have such a thing available in mathlib. Likely not much would be needed - I suspect the existing one is all I would need to work with.

#### Eric Wieser (Feb 21 2021 at 22:22):

A linter to catch the type of decidable / fintype instance problems I resolved above would likely help with avoiding some of these traps

#### Kevin Buzzard (Feb 21 2021 at 22:42):

Yes but I think the time has come now to do this -- and I'm about to sit down and do it -- because there are some people who simply never ever want to #eval anything and simply do not need the trouble which things like fintype and finset.sum can cause, especially if they open_locale classical on line 1 and then occasionally use types which have got decidable equality. It's just one extra hassle which doesn't need to be dealt with. Avigad told me that Isabelle has finsum and it works fine.

#### Kevin Buzzard (Feb 21 2021 at 22:45):

@Jason KY. I'll put you as co-author, I'll do it on the discord.

#### Mario Carneiro (Feb 22 2021 at 01:19):

It's not just #eval, when it comes to facts about small matrices or something dec_trivial can sometimes be the most powerful tool at our disposal

#### Mario Carneiro (Feb 22 2021 at 01:20):

That's not a great situation, since that approach has a host of limitations, but it is what it is

#### Mario Carneiro (Feb 22 2021 at 01:24):

That said I'm in agreement on the introduction of fincard and finsum FWIW. There are just a lot of lemmas that are needed to make this nice - I found at least two or three in my proof above, regarding the interaction between set.to_finset and all of the finset API; with a finsum API we also need lemmas relating it to finset sum, and also copies of everything in the finset sum API.

#### Kevin Buzzard (Feb 22 2021 at 02:08):

First attempt to make a finsum API is #6355. Many thanks to @Jason KY. who did most of the work.

#### Kevin Buzzard (Feb 22 2021 at 02:10):

@Peter Nelson we don't make propositional finite types because we can just use nonempty (fintype α). We don't do cardinality yet, that is some work we have prepared but haven't got into PR shape yet. This might take some time to get through the system.

#### Peter Nelson (Feb 22 2021 at 02:36):

That sounds great - I look forward to tinkering tomorrow.

Might there be a case for also adding finmax to the API? It is a special case of finsum (and could be defined as such), but API lemmas in which maxima are taken over subsets etc could be useful. Something I'm currently doing uses fintype.exists_max + choice to define a maximum, and I haven't run into any mismatch issues so far, but who knows what will happen in the future.

#### Peter Nelson (Feb 22 2021 at 02:47):

variables {α β : Type u}[linear_order β]

noncomputable def finmax (f : α  β) : β := sorry
-- some default value if no max exists, otherwise the max

lemma finmax_is_max [nonempty α][nonempty (fintype α)](f : α  β):  x, f x  finmax f := sorry

lemma exists_argmax  [nonempty α][nonempty (fintype α)](f : α  β):  x,  f x = finmax f  := sorry

etc etc

#### Mario Carneiro (Feb 22 2021 at 02:51):

That seems very near to what supr already does

#### Mario Carneiro (Feb 22 2021 at 02:52):

we just need a version of supr that works on any preorder

#### Peter Nelson (Feb 22 2021 at 02:54):

The existence of an argmax following from (propositional) finiteness is what I'm after. I can't see anything about finiteness in the supr API, but maybe I'm missing something?

#### Mario Carneiro (Feb 22 2021 at 02:54):

finite lattices are complete

#### Peter Nelson (Feb 22 2021 at 02:56):

Is there a fintype hiding there somewhere?

#### Mario Carneiro (Feb 22 2021 at 02:57):

My point is that for the finmax function, you don't need any inputs except for preorder B and nonempty A, and it can be well defined whenever anything like it makes sense; you can then prove that it makes sense when A is finite to make use of it in your scenario

#### Mario Carneiro (Feb 22 2021 at 02:58):

there's no need to bake finiteness into the definition though

#### Mario Carneiro (Feb 22 2021 at 03:00):

actually nonempty B is probably better than nonempty A here, that way it can default to the zero of the codomain instead of a random value

#### Mario Carneiro (Feb 22 2021 at 03:01):

inhabited B is probably better

#### Peter Nelson (Feb 22 2021 at 03:05):

Ah, it looks like set.finite.exists_maximal_wrt already does what I want , without any fintype. Here it is:

theorem set.finite.exists_maximal_wrt {α : Type u} {β : Type v} [partial_order β]
(f : α  β)(s : set α) (h : s.finite) :
s.nonempty  ( (a : α) (H : a  s),  (a' : α), a'  s  f a  f a'  f a = f a')

Or not quite, but it's easy to get a linear_order version.

#### Peter Nelson (Mar 05 2021 at 15:49):

@Kevin Buzzard @Jason KY. I've started incorporating finsum into my project, as well as rolling my own fincard by finsumming ones (I'm assuming the intended implementation of fincard is more principled, but mine will do for now). It's great avoiding the mismatches, and what's more, not to have to regularly descend into finset coercion hell in the first place!

I have a question about intended usage. For most of my interaction with finsum, everything will be happening with variables {\a : Type} [nonempty (fintype \a)] at the top of files. But this will mean that for each of the finsum and finsum_in lemmas that require explicit finiteness assumptions (which already each come in a few different flavours) , there will be yet another version that takes a nonempty fintype instance. For example, here are statements of a lemma I proved and its version that takes an instance.

lemma finsum_le_finsum [ordered_add_comm_monoid M](hfg :  x, f x  g x)
(hf : (function.support f).finite)(hg : (function.support g).finite):
∑ᶠ (i : α), f i  ∑ᶠ (i : α), g i :=
sorry

lemma finsum_le_finsum' [ordered_add_comm_monoid M][nonempty (fintype α)]
(hfg :  x, f x  g x):
∑ᶠ (i : α), f i  ∑ᶠ (i : α), g i :=
sorry

Is doing this for every such lemma a reasonable solution? I can't even think of a good naming convention.

#### Jason KY. (Mar 05 2021 at 17:09):

I think the idea is you prove the different versions if you are writing APIs (e.g. your example) while if you are simply using finsum you can just stick to one version (or the most general version, i.e. the support is finite.). @Mario Carneiro suggest a naming scheme here

Last updated: Aug 03 2023 at 10:10 UTC