Documentation

Init.Data.List.Monadic

Lemmas about List.mapM and List.forM. #

Monadic operations #

mapM #

def List.mapM' {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] (f : αm β) :
List αm (List β)

Alternate (non-tail-recursive) form of mapM for proofs.

Equations
Instances For
    @[simp]
    theorem List.mapM'_nil {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] {f : αm β} :
    List.mapM' f [] = pure []
    @[simp]
    theorem List.mapM'_cons {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} {a : α} {l : List α} [Monad m] {f : αm β} :
    List.mapM' f (a :: l) = do let __do_liftf a let __do_lift_1List.mapM' f l pure (__do_lift :: __do_lift_1)
    theorem List.mapM'_eq_mapM {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (f : αm β) (l : List α) :
    theorem List.mapM'_eq_mapM.go {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (f : αm β) (l : List α) (acc : List β) :
    List.mapM.loop f l acc = do let __do_liftList.mapM' f l pure (acc.reverse ++ __do_lift)
    @[simp]
    theorem List.mapM_nil {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] (f : αm β) :
    List.mapM f [] = pure []
    @[simp]
    theorem List.mapM_cons {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} {a : α} {l : List α} [Monad m] [LawfulMonad m] (f : αm β) :
    List.mapM f (a :: l) = do let __do_liftf a let __do_lift_1List.mapM f l pure (__do_lift :: __do_lift_1)
    @[simp]
    theorem List.mapM_id {α : Type u_1} {β : Type u_2} {l : List α} {f : αId β} :
    @[simp]
    theorem List.mapM_append {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (f : αm β) {l₁ l₂ : List α} :
    List.mapM f (l₁ ++ l₂) = do let __do_liftList.mapM f l₁ let __do_lift_1List.mapM f l₂ pure (__do_lift ++ __do_lift_1)
    theorem List.foldlM_cons_eq_append {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (f : αm β) (as : List α) (b : β) (bs : List β) :
    List.foldlM (fun (acc : List β) (a : α) => do let __do_liftf a pure (__do_lift :: acc)) (b :: bs) as = (fun (x : List β) => x ++ b :: bs) <$> List.foldlM (fun (acc : List β) (a : α) => do let __do_liftf a pure (__do_lift :: acc)) [] as

    Auxiliary lemma for mapM_eq_reverse_foldlM_cons.

    theorem List.mapM_eq_reverse_foldlM_cons {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (f : αm β) (l : List α) :
    List.mapM f l = List.reverse <$> List.foldlM (fun (acc : List β) (a : α) => do let __do_liftf a pure (__do_lift :: acc)) [] l

    foldlM and foldrM #

    theorem List.foldlM_map {m : Type u_1 → Type u_2} {β₁ : Type u_3} {β₂ : Type u_4} {α : Type u_1} [Monad m] (f : β₁β₂) (g : αβ₂m α) (l : List β₁) (init : α) :
    List.foldlM g init (List.map f l) = List.foldlM (fun (x : α) (y : β₁) => g x (f y)) init l
    theorem List.foldrM_map {m : Type u_1 → Type u_2} {β₁ : Type u_3} {β₂ : Type u_4} {α : Type u_1} [Monad m] [LawfulMonad m] (f : β₁β₂) (g : β₂αm α) (l : List β₁) (init : α) :
    List.foldrM g init (List.map f l) = List.foldrM (fun (x : β₁) (y : α) => g (f x) y) init l
    theorem List.foldlM_filterMap {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_4} {γ : Type u_1} [Monad m] [LawfulMonad m] (f : αOption β) (g : γβm γ) (l : List α) (init : γ) :
    List.foldlM g init (List.filterMap f l) = List.foldlM (fun (x : γ) (y : α) => match f y with | some b => g x b | none => pure x) init l
    theorem List.foldrM_filterMap {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_4} {γ : Type u_1} [Monad m] [LawfulMonad m] (f : αOption β) (g : βγm γ) (l : List α) (init : γ) :
    List.foldrM g init (List.filterMap f l) = List.foldrM (fun (x : α) (y : γ) => match f x with | some b => g b y | none => pure y) init l
    theorem List.foldlM_filter {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (p : αBool) (g : βαm β) (l : List α) (init : β) :
    List.foldlM g init (List.filter p l) = List.foldlM (fun (x : β) (y : α) => if p y = true then g x y else pure x) init l
    theorem List.foldrM_filter {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (p : αBool) (g : αβm β) (l : List α) (init : β) :
    List.foldrM g init (List.filter p l) = List.foldrM (fun (x : α) (y : β) => if p x = true then g x y else pure y) init l

    forM #

    @[simp]
    theorem List.forM_nil' {m : Type u_1 → Type u_2} {α : Type u_3} {f : αm PUnit} [Monad m] :
    [].forM f = pure PUnit.unit
    @[simp]
    theorem List.forM_cons' {m : Type u_1 → Type u_2} {α✝ : Type u_3} {a : α✝} {as : List α✝} {f : α✝m PUnit} [Monad m] :
    (a :: as).forM f = do f a as.forM f
    @[simp]
    theorem List.forM_append {m : Type u_1 → Type u_2} {α : Type u_3} [Monad m] [LawfulMonad m] (l₁ l₂ : List α) (f : αm PUnit) :
    (l₁ ++ l₂).forM f = do l₁.forM f l₂.forM f

    forIn' #

    theorem List.forIn'_loop_congr {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} {xs : List α} [Monad m] {as bs : List α} {f : (a' : α) → a' asβm (ForInStep β)} {g : (a' : α) → a' bsβm (ForInStep β)} {b : β} (ha : ∃ (ys : List α), ys ++ xs = as) (hb : ∃ (ys : List α), ys ++ xs = bs) (h : ∀ (a : α) (m_1 : a as) (m' : a bs) (b : β), f a m_1 b = g a m' b) :
    List.forIn'.loop as f xs b ha = List.forIn'.loop bs g xs b hb
    @[simp]
    theorem List.forIn'_cons {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] {a : α} {as : List α} (f : (a' : α) → a' a :: asβm (ForInStep β)) (b : β) :
    forIn' (a :: as) b f = do let xf a b match x with | ForInStep.done b => pure b | ForInStep.yield b => forIn' as b fun (a' : α) (m : a' as) (b : β) => f a' b
    @[simp]
    theorem List.forIn_cons {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] (f : αβm (ForInStep β)) (a : α) (as : List α) (b : β) :
    forIn (a :: as) b f = do let xf a b match x with | ForInStep.done b => pure b | ForInStep.yield b => forIn as b f
    theorem List.forIn'_congr {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] {as bs : List α} (w : as = bs) {b b' : β} (hb : b = b') {f : (a' : α) → a' asβm (ForInStep β)} {g : (a' : α) → a' bsβm (ForInStep β)} (h : ∀ (a : α) (m_1 : a bs) (b : β), f a b = g a m_1 b) :
    forIn' as b f = forIn' bs b' g
    theorem List.forIn'_eq_foldlM {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (l : List α) (f : (a : α) → a lβm (ForInStep β)) (init : β) :
    forIn' l init f = ForInStep.value <$> List.foldlM (fun (b : ForInStep β) (x : { x : α // x l }) => match x with | a, m_1 => match b with | ForInStep.yield b => f a m_1 b | ForInStep.done b => pure (ForInStep.done b)) (ForInStep.yield init) l.attach

    We can express a for loop over a list as a fold, in which whenever we reach .done b we keep that value through the rest of the fold.

    @[simp]
    theorem List.forIn'_yield_eq_foldlM {m : Type u_1 → Type u_2} {α : Type u_3} {β γ : Type u_1} [Monad m] [LawfulMonad m] (l : List α) (f : (a : α) → a lβm γ) (g : (a : α) → a lβγβ) (init : β) :
    (forIn' l init fun (a : α) (m_1 : a l) (b : β) => (fun (c : γ) => ForInStep.yield (g a m_1 b c)) <$> f a m_1 b) = List.foldlM (fun (b : β) (x : { x : α // x l }) => match x with | a, m_1 => g a m_1 b <$> f a m_1 b) init l.attach

    We can express a for loop over a list which always yields as a fold.

    theorem List.forIn'_pure_yield_eq_foldl {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (l : List α) (f : (a : α) → a lββ) (init : β) :
    (forIn' l init fun (a : α) (m_1 : a l) (b : β) => pure (ForInStep.yield (f a m_1 b))) = pure (List.foldl (fun (b : β) (x : { x : α // x l }) => match x with | a, h => f a h b) init l.attach)
    @[simp]
    theorem List.forIn'_yield_eq_foldl {α : Type u_1} {β : Type u_2} (l : List α) (f : (a : α) → a lββ) (init : β) :
    (forIn' l init fun (a : α) (m : a l) (b : β) => ForInStep.yield (f a m b)) = List.foldl (fun (b : β) (x : { x : α // x l }) => match x with | a, h => f a h b) init l.attach
    theorem List.forIn_eq_foldlM {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (f : αβm (ForInStep β)) (init : β) (l : List α) :
    forIn l init f = ForInStep.value <$> List.foldlM (fun (b : ForInStep β) (a : α) => match b with | ForInStep.yield b => f a b | ForInStep.done b => pure (ForInStep.done b)) (ForInStep.yield init) l

    We can express a for loop over a list as a fold, in which whenever we reach .done b we keep that value through the rest of the fold.

    @[simp]
    theorem List.forIn_yield_eq_foldlM {m : Type u_1 → Type u_2} {α : Type u_3} {β γ : Type u_1} [Monad m] [LawfulMonad m] (l : List α) (f : αβm γ) (g : αβγβ) (init : β) :
    (forIn l init fun (a : α) (b : β) => (fun (c : γ) => ForInStep.yield (g a b c)) <$> f a b) = List.foldlM (fun (b : β) (a : α) => g a b <$> f a b) init l

    We can express a for loop over a list which always yields as a fold.

    theorem List.forIn_pure_yield_eq_foldl {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (l : List α) (f : αββ) (init : β) :
    (forIn l init fun (a : α) (b : β) => pure (ForInStep.yield (f a b))) = pure (List.foldl (fun (b : β) (a : α) => f a b) init l)
    @[simp]
    theorem List.forIn_yield_eq_foldl {α : Type u_1} {β : Type u_2} (l : List α) (f : αββ) (init : β) :
    (forIn l init fun (a : α) (b : β) => ForInStep.yield (f a b)) = List.foldl (fun (b : β) (a : α) => f a b) init l

    allM #

    theorem List.allM_eq_not_anyM_not {m : TypeType u_1} {α : Type u_2} [Monad m] [LawfulMonad m] (p : αm Bool) (as : List α) :
    List.allM p as = (fun (x : Bool) => !x) <$> List.anyM (fun (x : α) => (fun (x : Bool) => !x) <$> p x) as