Zulip Chat Archive

Stream: new members

Topic: Need help understanding behaviour of Fin


Kevin Cheung (Apr 02 2024 at 15:03):

I am a bit puzzled by what's happening in the code below:

import Mathlib.Data.Fin.Basic
-- import Mathlib.Data.Real.Sqrt

def z := (5 : Fin 3) -- Why does this work?
#check z -- This shows z : Fin 3.

def f (n : Fin 5) := n * 2
#reduce f (9 : ) -- This gives a type error.

The error for the last line:

application type mismatch
  f 9
argument
  9
has type
   : Type
but is expected to have type
  Fin 5 : Type

Interestingly, if I replace the import with import Mathlib.Data.Real.Sqrt, there is no error anywhere. If anyone could shed some light on what's happening, it'll be greatly appreciated.

Mario Carneiro (Apr 02 2024 at 15:12):

Fin 3 has an OfNat instance in core, meaning that (5 : Fin 3) compiles (it wraps BTW), but there is no NatCast instance and IntCast doesn't even exist in core, so

#check fun n : Nat => (n : Fin 3)
#check fun n : Int => (n : Fin 3)

do not compile. Mathlib adds instances of these classes for any ring, and Fin 3 is a ring, so after importing enough of mathlib it does compile (it wraps)

Kevin Cheung (Apr 02 2024 at 15:14):

I see. Is there a way for disable this kind of casting (i.e. disallowing wrapping)?

Kevin Cheung (Apr 02 2024 at 15:16):

Should one use Finset.range 3 instead of Fin 3?

Mario Carneiro (Apr 02 2024 at 15:17):

In principle yes. The reason the OfNat A n class takes n as a parameter is so that you can specify separately that a type has only certain numbers, so you could make (3 : MyFin 5) compile and (5 : MyFin 3) not. But I don't think you can get rid of the existing instance on Fin itself without using attribute [-instance], which isn't a very long term solution since it's file-local

Mario Carneiro (Apr 02 2024 at 15:19):

Kevin Cheung said:

Should one use Finset.range 3 instead of Fin 3?

These have different types (one is a Finset and the other is a type), they aren't directly interchangeable. Maybe it would help to elaborate on what you need this for?

Kevin Cheung (Apr 02 2024 at 15:21):

I am wondering how to formulate something that involves

a0,,ana_0,\ldots,a_n

wonder if it's better to use Finset.range or Fin for the indexing.

Kevin Cheung (Apr 02 2024 at 15:23):

For example,

import Mathlib.Algebra.BigOperators.Fin
import Mathlib.Data.Finset.Basic
import Mathlib.Data.Real.Sqrt

theorem my_cauchy_schwarz (n : ) (a : Fin n  ) (b : Fin n  ) :
    ( i : Fin n, (a i) * (b i) )  Real.sqrt ( i : Fin n, (a i) ^ 2) * Real.sqrt ( i : Fin n, (b i) ^ 2) := by sorry

Mario Carneiro (Apr 02 2024 at 15:24):

that's actually still not enough information. The translation of sequences in traditional mathematics can be quite varied depending on what else is going on in the statement; often the conclusion is to use arbitrary finite indexing sets, sets of values or in some cases completely reformulating the statement (e.g. using filters)

Mario Carneiro (Apr 02 2024 at 15:24):

In your my_cauchy_schwarz example, I would be inclined to use an arbitrary sum over a Finset there

Kevin Cheung (Apr 02 2024 at 15:25):

Mario Carneiro said:

In your my_cauchy_schwarz example, I would be inclined to use an arbitrary sum over a Finset there

What would that look like, if you don't mind giving more details?

Mario Carneiro (Apr 02 2024 at 15:25):

import Mathlib.Algebra.BigOperators.Fin
import Mathlib.Data.Finset.Basic
import Mathlib.Data.Real.Sqrt

open BigOperators

theorem my_cauchy_schwarz (s : Finset α) (a : α  ) (b : α  ) :
    ( i in s, (a i) * (b i) )  Real.sqrt ( i in s, (a i) ^ 2) * Real.sqrt ( i in s, (b i) ^ 2) := by sorry

Mario Carneiro (Apr 02 2024 at 15:27):

this directly specializes to the statement you gave:

theorem my_cauchy_schwarz' (n : ) (a : Fin n  ) (b : Fin n  ) :
    ( i : Fin n, (a i) * (b i) )  Real.sqrt ( i : Fin n, (a i) ^ 2) * Real.sqrt ( i : Fin n, (b i) ^ 2) :=
  my_cauchy_schwarz ..

Kevin Cheung (Apr 02 2024 at 15:28):

Interesting. Thank you.

Kevin Cheung (Apr 02 2024 at 15:29):

I always get confused between Finset.range and Fin.

Mario Carneiro (Apr 02 2024 at 15:31):

Finset A is a finite subset of elements of A. Finset.range n : Finset Nat is the collection of all numbers less than n, as a Finset of natural numbers. Fin n is an abstract type with n elements, which can be naturally embedded in Nat using the .val function

Kevin Cheung (Apr 02 2024 at 17:27):

Thank you for the explanation.

Yaël Dillies (Apr 02 2024 at 18:10):

Here is the mathlib statement for reference: docs#sum_mul_le_sqrt_mul_sqrt

Kevin Cheung (Apr 02 2024 at 19:11):

Mario Carneiro said:

this directly specializes to the statement you gave:

theorem my_cauchy_schwarz' (n : ) (a : Fin n  ) (b : Fin n  ) :
    ( i : Fin n, (a i) * (b i) )  Real.sqrt ( i : Fin n, (a i) ^ 2) * Real.sqrt ( i : Fin n, (b i) ^ 2) :=
  my_cauchy_schwarz ..

What does .. in my_cauchy_schwarz .. do?

Adam Topaz (Apr 02 2024 at 19:15):

The .. means "put as many _ as needed"

Kevin Cheung (Apr 02 2024 at 19:18):

Hmm. In this case, I had to put four _ but my_cauchy_schwarz seems to take three arguments. Is one of them implicit here?

Adam Topaz (Apr 02 2024 at 19:21):

I only had to put 3:

import Mathlib.Algebra.BigOperators.Fin
import Mathlib.Data.Finset.Basic
import Mathlib.Data.Real.Sqrt

open BigOperators

theorem my_cauchy_schwarz (s : Finset α) (a : α  ) (b : α  ) :
    ( i in s, (a i) * (b i) )  Real.sqrt ( i in s, (a i) ^ 2) * Real.sqrt ( i in s, (b i) ^ 2) := by sorry

theorem my_cauchy_schwarz' (n : ) (a : Fin n  ) (b : Fin n  ) :
    ( i : Fin n, (a i) * (b i) )  Real.sqrt ( i : Fin n, (a i) ^ 2) * Real.sqrt ( i : Fin n, (b i) ^ 2) :=
  my_cauchy_schwarz _ _ _

Kevin Cheung (Apr 02 2024 at 19:21):

There is some magic that I still don't understand. If we have s : Finset α, how does ∑ i in s get specialized into ∑ i : Fin n?

Adam Topaz (Apr 02 2024 at 19:22):

s gets specialized to \top : Finset (Fin n)

Yaël Dillies (Apr 02 2024 at 19:22):

∑ i : Fin n is notation for ∑ i in (univ : Finset (Fin n))

Adam Topaz (Apr 02 2024 at 19:23):

right, univ not top.

Yaël Dillies (Apr 02 2024 at 19:23):

Same thing soon (hopefully) :smile: :fingers_crossed:

Kevin Cheung (Apr 02 2024 at 19:26):

Adam Topaz said:

I only had to put 3:

import Mathlib.Algebra.BigOperators.Fin
import Mathlib.Data.Finset.Basic
import Mathlib.Data.Real.Sqrt

open BigOperators

theorem my_cauchy_schwarz (s : Finset α) (a : α  ) (b : α  ) :
    ( i in s, (a i) * (b i) )  Real.sqrt ( i in s, (a i) ^ 2) * Real.sqrt ( i in s, (b i) ^ 2) := by sorry

theorem my_cauchy_schwarz' (n : ) (a : Fin n  ) (b : Fin n  ) :
    ( i : Fin n, (a i) * (b i) )  Real.sqrt ( i : Fin n, (a i) ^ 2) * Real.sqrt ( i : Fin n, (b i) ^ 2) :=
  my_cauchy_schwarz _ _ _

I see why. I had autoimplicit = false and declared α explicitly.

Kevin Cheung (Apr 02 2024 at 19:28):

Yaël Dillies said:

Same thing soon (hopefully) :smile: :fingers_crossed:

There is a difference between univ and top?

Yaël Dillies (Apr 02 2024 at 19:29):

They are definitionally equal (so Finset.univ = ⊤ can be proved by rfl), however they are not syntactically equal (so you can't use a lemma about one to rewrite the other)

Kevin Cheung (Apr 02 2024 at 20:04):

I see.


Last updated: May 02 2025 at 03:31 UTC