Documentation

ArkLib.Data.Fin.Fold

Folding over Fin #

This file defines the prime versions of Fin.(d)fold{l/r} which has better definitional equalities (i.e. automatically unfold for 0 and for n.succ). We then show equivalences between the prime and non-prime versions, so that when compiling, the non-prime versions (which are more efficient) are used.

We also prove that the existing mathlib function finSumFinEquiv : ∑ i, Fin (n i) ≃ Fin (∑ i, n i) is equivalent to a version defined via Fin.dfoldl'.

def Fin.dfoldlM' {m : Type u → Type v} [Monad m] (n : ) (α : Fin (n + 1)Type u) (f : (i : Fin n) → α i.castSuccm (α i.succ)) (init : α 0) :
m (α (last n))

Heterogeneous left fold over Fin n in a monad, prime version with better defeq. Automatically unfolds for 0 and n.succ.

Equations
    Instances For
      @[simp]
      theorem Fin.dfoldlM'_zero {m : Type u → Type v} [Monad m] {α : Fin 1Type u} (f : (i : Fin 0) → α i.castSuccm (α i.succ)) (x : α 0) :
      dfoldlM' 0 α f x = pure x
      @[simp]
      theorem Fin.dfoldlM'_succ {m : Type u → Type v} [Monad m] {n : } {α : Fin (n + 2)Type u} (f : (i : Fin (n + 1)) → α i.castSuccm (α i.succ)) (x : α 0) :
      dfoldlM' (n + 1) α f x = do let ydfoldlM' n (α castSucc) (fun (i : Fin n) => f i.castSucc) x f (last n) y
      def Fin.dfoldl' (n : ) (α : Fin (n + 1)Type u) (f : (i : Fin n) → α i.castSuccα i.succ) (init : α 0) :
      α (last n)

      Heterogeneous left fold over Fin n, prime version with better defeq. Automatically unfolds for 0 and n.succ.

      Equations
        Instances For
          @[simp]
          theorem Fin.dfoldl'_zero {α : Fin 1Type u} (f : (i : Fin 0) → α i.castSuccα i.succ) (x : α 0) :
          dfoldl' 0 α f x = x
          @[simp]
          theorem Fin.dfoldl'_succ_last {n : } {α : Fin (n + 2)Type u} (f : (i : Fin (n + 1)) → α i.castSuccα i.succ) (x : α 0) :
          dfoldl' (n + 1) α f x = f (last n) (dfoldl' n (α castSucc) (fun (i : Fin n) => f i.castSucc) x)
          @[csimp]

          Compiler replacement rule: use dfoldl' instead of dfoldl for better defeq.

          def Fin.foldl' {α : Type u} (n : ) (f : Fin nαα) (init : α) :
          α

          Left fold over Fin n, prime version with better defeq. Automatically unfolds for 0 and n.succ.

          Equations
            Instances For
              @[simp]
              theorem Fin.foldl'_zero {α : Type u} (f : Fin 0αα) (x : α) :
              foldl' 0 f x = x
              @[simp]
              theorem Fin.foldl'_succ {n : } {α : Type u} (f : Fin (n + 1)αα) (x : α) :
              foldl' (n + 1) f x = f (last n) (foldl' n (fun (i : Fin n) => f i.castSucc) x)
              def Fin.dfoldrM' {m : Type u → Type v} [Monad m] (n : ) (α : Fin (n + 1)Type u) (f : (i : Fin n) → α i.succm (α i.castSucc)) (init : α (last n)) :
              m (α 0)

              Heterogeneous right fold over Fin n in a monad, prime version with better defeq. Automatically unfolds for 0 and n.succ.

              Equations
                Instances For
                  @[simp]
                  theorem Fin.dfoldrM'_zero {m : Type u → Type v} [Monad m] {α : Fin 1Type u} (f : (i : Fin 0) → α i.succm (α i.castSucc)) (x : α (last 0)) :
                  dfoldrM' 0 α f x = pure x
                  @[simp]
                  theorem Fin.dfoldrM'_succ {m : Type u → Type v} [Monad m] {n : } {α : Fin (n + 1 + 1)Type u} (f : (i : Fin (n + 1)) → α i.succm (α i.castSucc)) (x : α (last (n + 1))) :
                  dfoldrM' (n + 1) α f x = do let ydfoldrM' n (α succ) (fun (i : Fin n) => f i.succ) x f 0 y
                  def Fin.dfoldr' (n : ) (α : Fin (n + 1)Type u) (f : (i : Fin n) → α i.succα i.castSucc) (init : α (last n)) :
                  α 0

                  Heterogeneous right fold over Fin n, prime version with better defeq. Automatically unfolds for 0 and n.succ.

                  Equations
                    Instances For
                      @[simp]
                      theorem Fin.dfoldr'_zero {α : Fin 1Type u} (f : (i : Fin 0) → α i.succα i.castSucc) (x : α (last 0)) :
                      dfoldr' 0 α f x = x
                      @[simp]
                      theorem Fin.dfoldr'_succ {n : } {α : Fin (n + 1 + 1)Type u} (f : (i : Fin (n + 1)) → α i.succα i.castSucc) (x : α (last (n + 1))) :
                      dfoldr' (n + 1) α f x = f 0 (dfoldr' n (α succ) (fun (i : Fin n) => f i.succ) x)
                      @[csimp]

                      Compiler replacement rule: use dfoldr' instead of dfoldr for better defeq.

                      def Fin.foldr' {α : Type u} (n : ) (f : Fin nαα) (init : α) :
                      α

                      Right fold over Fin n, prime version with better defeq. Automatically unfolds for 0 and n.succ.

                      Equations
                        Instances For
                          @[simp]
                          theorem Fin.foldr'_zero {α : Type u} (f : Fin 0αα) (x : α) :
                          foldr' 0 f x = x
                          @[simp]
                          theorem Fin.foldr'_succ {n : } {α : Type u} (f : Fin (n + 1)αα) (x : α) :
                          foldr' (n + 1) f x = f 0 (foldr' n (f succ) x)
                          def Fin.IterType (n : ) :
                          Equations
                            Instances For
                              Equations
                                Instances For
                                  Equations
                                    Instances For
                                      theorem Fin.dfoldl_congr {n : } {α α' : Fin (n + 1)Type u} {f : (i : Fin n) → α i.castSuccα i.succ} {f' : (i : Fin n) → α' i.castSuccα' i.succ} {init : α 0} {init' : α' 0} ( : ∀ (i : Fin (n + 1)), α i = α' i) (hf : ∀ (i : Fin n) (a : α i.castSucc), f i a = cast (f' i (cast a))) (hinit : init = cast init') :
                                      dfoldl n α f init = cast (dfoldl n α' f' init')

                                      Congruence for dfoldl

                                      theorem Fin.dfoldl_congr_dcast {n : } {ι : Type v} {α α' : Fin (n + 1)ι} {β : ιType u} [DCast ι β] {f : (i : Fin n) → β (α i.castSucc)β (α i.succ)} {f' : (i : Fin n) → β (α' i.castSucc)β (α' i.succ)} {init : β (α 0)} {init' : β (α' 0)} ( : ∀ (i : Fin (n + 1)), α i = α' i) (hf : ∀ (i : Fin n) (a : β (α i.castSucc)), f i a = dcast (f' i (dcast a))) (hinit : init = dcast init') :
                                      dfoldl n (fun (i : Fin (n + 1)) => β (α i)) f init = cast (dfoldl n (fun (i : Fin (n + 1)) => β (α' i)) f' init')

                                      Congruence for dfoldl whose type vectors are indexed by ι and have a DCast instance

                                      Note that we put cast (instead of dcast) in the theorem statement for easier matching, but dcast inside the hypotheses for downstream proving.

                                      theorem Fin.dfoldl_dcast {ι : Type v} {β : ιType u} [DCast ι β] {n : } {α α' : Fin (n + 1)ι} {f : (i : Fin n) → β (α i.castSucc)β (α i.succ)} {init : β (α 0)} ( : ∀ (i : Fin (n + 1)), α i = α' i) :
                                      dcast (dfoldl n (fun (i : Fin (n + 1)) => β (α i)) f init) = dfoldl n (fun (i : Fin (n + 1)) => β (α' i)) (fun (i : Fin n) (a : (fun (i : Fin (n + 1)) => β (α' i)) i.castSucc) => dcast (f i (dcast a))) (dcast init)

                                      Distribute dcast inside dfoldl. Requires the minimal condition of α = α'