File: Mathlib/Control/Fold.lean

full_name: Monoid.Foldl
code: /-- For a list, foldl f x [y₀,y₁] reduces as follows:

```
calc  foldl f x [y₀,y₁]
    = foldl f (f x y₀) [y₁]      : rfl
... = foldl f (f (f x y₀) y₁) [] : rfl
... = f (f x y₀) y₁              : rfl
```
with
```
f : α → β → α
x : α
[y₀,y₁] : List β
```

We can view the above as a composition of functions:
```
... = f (f x y₀) y₁              : rfl
... = flip f y₁ (flip f y₀ x)    : rfl
... = (flip f y₁ ∘ flip f y₀) x  : rfl
```

We can use traverse and const to construct this composition:
```
calc   const.run (traverse (fun y ↦ const.mk' (flip f y)) [y₀,y₁]) x
     = const.run ((::) <$> const.mk' (flip f y₀) <*>
         traverse (fun y ↦ const.mk' (flip f y)) [y₁]) x
...  = const.run ((::) <$> const.mk' (flip f y₀) <*>
         ( (::) <$> const.mk' (flip f y₁) <*> traverse (fun y ↦ const.mk' (flip f y)) [] )) x
...  = const.run ((::) <$> const.mk' (flip f y₀) <*>
         ( (::) <$> const.mk' (flip f y₁) <*> pure [] )) x
...  = const.run ( ((::) <$> const.mk' (flip f y₁) <*> pure []) ∘
         ((::) <$> const.mk' (flip f y₀)) ) x
...  = const.run ( const.mk' (flip f y₁) ∘ const.mk' (flip f y₀) ) x
...  = const.run ( flip f y₁ ∘ flip f y₀ ) x
...  = f (f x y₀) y₁
```

And this is how `const` turns a monoid into an applicative functor and
how the monoid of endofunctions define `Foldl`.
-/
abbrev Foldl (α : Type u) : Type u 
goal: Type u

full_name: Monoid.Foldl.mk
code: def Foldl.mk (f : α → α) : Foldl α 
goal: Monoid.Foldl α

full_name: Monoid.Foldl.get
code: def Foldl.get (x : Foldl α) : α → α 
goal: α → α

full_name: Monoid.Foldl.ofFreeMonoid
code: @[simps]
def Foldl.ofFreeMonoid (f : β → α → β) : FreeMonoid α →* Monoid.Foldl β 
goal: FreeMonoid α →* Monoid.Foldl β

full_name: Monoid.Foldl.ofFreeMonoid_apply
code: @[simps]
def Foldl.ofFreeMonoid (f : β → α → β) : FreeMonoid α →* Monoid.Foldl β 
goal: (Monoid.Foldl.ofFreeMonoid f) xs = MulOpposite.op (flip (List.foldl f) (FreeMonoid.toList xs))

full_name: Monoid.Foldr
code: abbrev Foldr (α : Type u) : Type u 
goal: Type u

full_name: Monoid.Foldr.mk
code: def Foldr.mk (f : α → α) : Foldr α 
goal: Monoid.Foldr α

full_name: Monoid.Foldr.get
code: def Foldr.get (x : Foldr α) : α → α 
goal: α → α

full_name: Monoid.Foldr.ofFreeMonoid_apply
code: @[simps]
def Foldr.ofFreeMonoid (f : α → β → β) : FreeMonoid α →* Monoid.Foldr β 
goal: ∀ (a : β), (Monoid.Foldr.ofFreeMonoid f) xs a = flip (List.foldr f) (FreeMonoid.toList xs) a

full_name: Monoid.Foldr.ofFreeMonoid
code: @[simps]
def Foldr.ofFreeMonoid (f : α → β → β) : FreeMonoid α →* Monoid.Foldr β 
goal: FreeMonoid α →* Monoid.Foldr β

full_name: Monoid.foldlM
code: abbrev foldlM (m : Type u → Type u) [Monad m] (α : Type u) : Type u 
goal: Type u

full_name: Monoid.foldlM.mk
code: def foldlM.mk (f : α → m α) : foldlM m α 
goal: Monoid.foldlM m α

full_name: Monoid.foldlM.get
code: def foldlM.get (x : foldlM m α) : α → m α 
goal: α → m α

full_name: Monoid.foldlM.ofFreeMonoid
code: @[simps]
def foldlM.ofFreeMonoid [LawfulMonad m] (f : β → α → m β) : FreeMonoid α →* Monoid.foldlM m β 
goal: FreeMonoid α →* Monoid.foldlM m β

full_name: Monoid.foldlM.ofFreeMonoid_apply
code: @[simps]
def foldlM.ofFreeMonoid [LawfulMonad m] (f : β → α → m β) : FreeMonoid α →* Monoid.foldlM m β 
goal: (Monoid.foldlM.ofFreeMonoid f) xs = MulOpposite.op (flip (List.foldlM f) (FreeMonoid.toList xs))

full_name: Monoid.foldrM
code: abbrev foldrM (m : Type u → Type u) [Monad m] (α : Type u) : Type u 
goal: Type u

full_name: Monoid.foldrM.mk
code: def foldrM.mk (f : α → m α) : foldrM m α 
goal: Monoid.foldrM m α

full_name: Monoid.foldrM.get
code: def foldrM.get (x : foldrM m α) : α → m α 
goal: α → m α

full_name: Monoid.foldrM.ofFreeMonoid
code: @[simps]
def foldrM.ofFreeMonoid [LawfulMonad m] (f : α → β → m β) : FreeMonoid α →* Monoid.foldrM m β 
goal: FreeMonoid α →* Monoid.foldrM m β

full_name: Monoid.foldrM.ofFreeMonoid_apply
code: @[simps]
def foldrM.ofFreeMonoid [LawfulMonad m] (f : α → β → m β) : FreeMonoid α →* Monoid.foldrM m β 
goal: ∀ (a : CategoryTheory.KleisliCat.mk m β),
  (Monoid.foldrM.ofFreeMonoid f) xs a = flip (List.foldrM f) (FreeMonoid.toList xs) a

full_name: Traversable.foldMap
code: def foldMap {α ω} [One ω] [Mul ω] (f : α → ω) : t α → ω 
goal: t α → ω

full_name: Traversable.foldl
code: def foldl (f : α → β → α) (x : α) (xs : t β) : α 
goal: α

full_name: Traversable.foldr
code: def foldr (f : α → β → β) (x : β) (xs : t α) : β 
goal: β

full_name: Traversable.toList
code: /-- Conceptually, `toList` collects all the elements of a collection
in a list. This idea is formalized by

  `lemma toList_spec (x : t α) : toList x = foldMap FreeMonoid.mk x`.

The definition of `toList` is based on `foldl` and `List.cons` for
speed. It is faster than using `foldMap FreeMonoid.mk` because, by
using `foldl` and `List.cons`, each insertion is done in constant
time. As a consequence, `toList` performs in linear.

On the other hand, `foldMap FreeMonoid.mk` creates a singleton list
around each element and concatenates all the resulting lists. In
`xs ++ ys`, concatenation takes a time proportional to `length xs`. Since
the order in which concatenation is evaluated is unspecified, nothing
prevents each element of the traversable to be appended at the end
`xs ++ [x]` which would yield a `O(n²)` run time. -/
def toList : t α → List α 
goal: t α → List α

full_name: Traversable.length
code: def length (xs : t α) : ℕ 
goal: ℕ

full_name: Traversable.foldlm
code: def foldlm (f : α → β → m α) (x : α) (xs : t β) : m α 
goal: m α

full_name: Traversable.foldrm
code: def foldrm (f : α → β → m β) (x : β) (xs : t α) : m β 
goal: m β

full_name: Traversable.mapFold
code: def mapFold [Monoid α] [Monoid β] (f : α →* β) : ApplicativeTransformation (Const α) (Const β) 
goal: ApplicativeTransformation (Functor.Const α) (Functor.Const β)

full_name: Traversable.Free.map_eq_map
code: theorem Free.map_eq_map (f : α → β) (xs : List α) :
    f <$> xs = (FreeMonoid.toList (FreeMonoid.map f (FreeMonoid.ofList xs))) 
goal: f <$> xs = FreeMonoid.toList ((FreeMonoid.map f) (FreeMonoid.ofList xs))

full_name: Traversable.foldl.unop_ofFreeMonoid
code: theorem foldl.unop_ofFreeMonoid (f : β → α → β) (xs : FreeMonoid α) (a : β) :
    unop (Foldl.ofFreeMonoid f xs) a = List.foldl f a (FreeMonoid.toList xs) 
goal: MulOpposite.unop ((Monoid.Foldl.ofFreeMonoid f) xs) a = List.foldl f a (FreeMonoid.toList xs)

full_name: Traversable.foldMap_hom
code: theorem foldMap_hom [Monoid α] [Monoid β] (f : α →* β) (g : γ → α) (x : t γ) :
    f (foldMap g x) = foldMap (f ∘ g) x 
goal: f (Traversable.foldMap g x) = Traversable.foldMap (⇑f ∘ g) x

full_name: Traversable.foldMap_hom_free
code: theorem foldMap_hom_free [Monoid β] (f : FreeMonoid α →* β) (x : t α) :
    f (foldMap FreeMonoid.of x) = foldMap (f ∘ FreeMonoid.of) x 
goal: f (Traversable.foldMap FreeMonoid.of x) = Traversable.foldMap (⇑f ∘ FreeMonoid.of) x

full_name: Traversable.foldl.ofFreeMonoid_comp_of
code: @[simp]
theorem foldl.ofFreeMonoid_comp_of (f : α → β → α) :
    Foldl.ofFreeMonoid f ∘ FreeMonoid.of = Foldl.mk ∘ flip f 
goal: ⇑(Monoid.Foldl.ofFreeMonoid f) ∘ FreeMonoid.of = Monoid.Foldl.mk ∘ flip f

full_name: Traversable.foldr.ofFreeMonoid_comp_of
code: @[simp]
theorem foldr.ofFreeMonoid_comp_of (f : β → α → α) :
    Foldr.ofFreeMonoid f ∘ FreeMonoid.of = Foldr.mk ∘ f 
goal: ⇑(Monoid.Foldr.ofFreeMonoid f) ∘ FreeMonoid.of = Monoid.Foldr.mk ∘ f

full_name: Traversable.foldlm.ofFreeMonoid_comp_of
code: @[simp]
theorem foldlm.ofFreeMonoid_comp_of {m} [Monad m] [LawfulMonad m] (f : α → β → m α) :
    foldlM.ofFreeMonoid f ∘ FreeMonoid.of = foldlM.mk ∘ flip f 
goal: ⇑(Monoid.foldlM.ofFreeMonoid f) ∘ FreeMonoid.of = Monoid.foldlM.mk ∘ flip f

full_name: Traversable.foldrm.ofFreeMonoid_comp_of
code: @[simp]
theorem foldrm.ofFreeMonoid_comp_of {m} [Monad m] [LawfulMonad m] (f : β → α → m α) :
    foldrM.ofFreeMonoid f ∘ FreeMonoid.of = foldrM.mk ∘ f 
goal: ⇑(Monoid.foldrM.ofFreeMonoid f) ∘ FreeMonoid.of = Monoid.foldrM.mk ∘ f

full_name: Traversable.toList_spec
code: theorem toList_spec (xs : t α) : toList xs = FreeMonoid.toList (foldMap FreeMonoid.of xs) 
goal: Traversable.toList xs = FreeMonoid.toList (Traversable.foldMap FreeMonoid.of xs)

full_name: Traversable.foldMap_map
code: theorem foldMap_map [Monoid γ] (f : α → β) (g : β → γ) (xs : t α) :
    foldMap g (f <$> xs) = foldMap (g ∘ f) xs 
goal: Traversable.foldMap g (f <$> xs) = Traversable.foldMap (g ∘ f) xs

full_name: Traversable.foldl_toList
code: theorem foldl_toList (f : α → β → α) (xs : t β) (x : α) :
    foldl f x xs = List.foldl f x (toList xs) 
goal: Traversable.foldl f x xs = List.foldl f x (Traversable.toList xs)

full_name: Traversable.foldr_toList
code: theorem foldr_toList (f : α → β → β) (xs : t α) (x : β) :
    foldr f x xs = List.foldr f x (toList xs) 
goal: Traversable.foldr f x xs = List.foldr f x (Traversable.toList xs)

full_name: Traversable.toList_map
code: theorem toList_map (f : α → β) (xs : t α) : toList (f <$> xs) = f <$> toList xs 
goal: Traversable.toList (f <$> xs) = f <$> Traversable.toList xs

full_name: Traversable.foldl_map
code: @[simp]
theorem foldl_map (g : β → γ) (f : α → γ → α) (a : α) (l : t β) :
    foldl f a (g <$> l) = foldl (fun x y => f x (g y)) a l 
goal: Traversable.foldl f a (g <$> l) = Traversable.foldl (fun x y => f x (g y)) a l

full_name: Traversable.foldr_map
code: @[simp]
theorem foldr_map (g : β → γ) (f : γ → α → α) (a : α) (l : t β) :
    foldr f a (g <$> l) = foldr (f ∘ g) a l 
goal: Traversable.foldr f a (g <$> l) = Traversable.foldr (f ∘ g) a l

full_name: Traversable.toList_eq_self
code: @[simp]
theorem toList_eq_self {xs : List α} : toList xs = xs 
goal: Traversable.toList xs = xs

full_name: Traversable.length_toList
code: theorem length_toList {xs : t α} : length xs = List.length (toList xs) 
goal: Traversable.length xs = (Traversable.toList xs).length

full_name: Traversable.foldlm_toList
code: theorem foldlm_toList {f : α → β → m α} {x : α} {xs : t β} :
    foldlm f x xs = List.foldlM f x (toList xs) 
goal: Traversable.foldlm f x xs = List.foldlM f x (Traversable.toList xs)

full_name: Traversable.foldrm_toList
code: theorem foldrm_toList (f : α → β → m β) (x : β) (xs : t α) :
    foldrm f x xs = List.foldrM f x (toList xs) 
goal: Traversable.foldrm f x xs = List.foldrM f x (Traversable.toList xs)

full_name: Traversable.foldlm_map
code: @[simp]
theorem foldlm_map (g : β → γ) (f : α → γ → m α) (a : α) (l : t β) :
    foldlm f a (g <$> l) = foldlm (fun x y => f x (g y)) a l 
goal: Traversable.foldlm f a (g <$> l) = Traversable.foldlm (fun x y => f x (g y)) a l

full_name: Traversable.foldrm_map
code: @[simp]
theorem foldrm_map (g : β → γ) (f : γ → α → m α) (a : α) (l : t β) :
    foldrm f a (g <$> l) = foldrm (f ∘ g) a l 
goal: Traversable.foldrm f a (g <$> l) = Traversable.foldrm (f ∘ g) a l