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.

Note that we can not have this as the main definition and replace it using a @[csimp] lemma, because they are only equal when m is a LawfulMonad.

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 β} :
    @[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 β} :
    mapM' f (a :: l) = do let __do_liftf a let __do_lift_1mapM' 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 α) :
    mapM' f l = mapM f l
    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 β) :
    mapM.loop f l acc = do let __do_liftmapM' 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 β) :
    @[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 β) :
    mapM f (a :: l) = do let __do_liftf a let __do_lift_1mapM f l pure (__do_lift :: __do_lift_1)
    @[simp]
    theorem List.mapM_id {α : Type u_1} {β : Type u_2} {l : List α} {f : αId β} :
    mapM f l = map f l
    @[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 α} :
    mapM f (l₁ ++ l₂) = do let __do_liftmapM f l₁ let __do_lift_1mapM 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 α) :
    mapM f l = reverse <$> List.foldlM (fun (acc : List β) (a : α) => do let __do_liftf a pure (__do_lift :: acc)) [] l

    filterMapM #

    @[simp]
    theorem List.filterMapM_nil {m : Type u_1 → Type u_2} {α β : Type u_1} [Monad m] (f : αm (Option β)) :
    theorem List.filterMapM_loop_eq {m : Type u_1 → Type u_2} {α β : Type u_1} [Monad m] [LawfulMonad m] (f : αm (Option β)) (l : List α) (acc : List β) :
    filterMapM.loop f l acc = (fun (x : List β) => acc.reverse ++ x) <$> filterMapM.loop f l []
    @[simp]
    theorem List.filterMapM_cons {m : Type u_1 → Type u_2} {α β : Type u_1} {a : α} {l : List α} [Monad m] [LawfulMonad m] (f : αm (Option β)) :
    filterMapM f (a :: l) = do let __do_liftf a match __do_lift with | none => filterMapM f l | some b => do let __do_liftfilterMapM f l pure (b :: __do_lift)

    flatMapM #

    @[simp]
    theorem List.flatMapM_nil {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] (f : αm (List β)) :
    theorem List.flatMapM_loop_eq {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (f : αm (List β)) (l : List α) (acc : List (List β)) :
    flatMapM.loop f l acc = (fun (x : List β) => acc.reverse.flatten ++ x) <$> flatMapM.loop f l []
    @[simp]
    theorem List.flatMapM_cons {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} {a : α} {l : List α} [Monad m] [LawfulMonad m] (f : αm (List β)) :
    flatMapM f (a :: l) = do let bsf a let __do_liftflatMapM f l pure (bs ++ __do_lift)

    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 (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 : α) :
    foldrM g init (map f l) = 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 (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 : γ) :
    foldrM g init (filterMap f l) = 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 (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 : β) :
    foldrM g init (filter p l) = foldrM (fun (x : α) (y : β) => if p x = true then g x y else pure y) init l
    @[simp]
    theorem List.foldlM_attachWith {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] (l : List α) {q : αProp} (H : ∀ (a : α), a lq a) {f : β{ x : α // q x }m β} {b : β} :
    List.foldlM f b (l.attachWith q H) = List.foldlM (fun (b : β) (x : { x : α // x l }) => match x with | a, h => f b a, ) b l.attach
    @[simp]
    theorem List.foldrM_attachWith {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] (l : List α) {q : αProp} (H : ∀ (a : α), a lq a) {f : { x : α // q x }βm β} {b : β} :
    foldrM f b (l.attachWith q H) = foldrM (fun (a : { x : α // x l }) (acc : β) => f a.val, acc) b l.attach

    forM #

    @[deprecated List.forM_nil (since := "2025-01-31")]
    theorem List.forM_nil' {m : Type u_1 → Type u_2} {α : Type u_3} {f : αm PUnit} [Monad m] :
    @[deprecated List.forM_cons (since := "2025-01-31")]
    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) :
    forM (l₁ ++ l₂) f = do forM l₁ f forM l₂ f
    @[simp]
    theorem List.forM_map {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_4} [Monad m] [LawfulMonad m] (l : List α) (g : αβ) (f : βm PUnit) :
    forM (map g l) f = forM l fun (a : α) => f (g a)

    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) :
    forIn'.loop as f xs b ha = 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 (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)) = foldl (fun (b : β) (x : { x : α // x l }) => match x with | a, h => f a h b) init l.attach
    @[simp]
    theorem List.forIn'_map {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_4} {γ : Type u_1} {init : γ} [Monad m] [LawfulMonad m] (l : List α) (g : αβ) (f : (b : β) → b map g lγm (ForInStep γ)) :
    forIn' (map g l) init f = forIn' l init fun (a : α) (h : a l) (y : γ) => f (g a) y
    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 (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)) = foldl (fun (b : β) (a : α) => f a b) init l
    @[simp]
    theorem List.forIn_map {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_4} {γ : Type u_1} {init : γ} [Monad m] [LawfulMonad m] (l : List α) (g : αβ) (f : βγm (ForInStep γ)) :
    forIn (map g l) init f = forIn l init fun (a : α) (y : γ) => f (g a) y

    allM #

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

    Recognizing higher order functions using a function that only depends on the value. #

    @[simp]
    theorem List.foldlM_subtype {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] {p : αProp} {l : List { x : α // p x }} {f : β{ x : α // p x }m β} {g : βαm β} {x : β} (hf : ∀ (b : β) (x : α) (h : p x), f b x, h = g b x) :

    This lemma identifies monadic folds over lists of subtypes, where the function only depends on the value, not the proposition, and simplifies these to the function directly taking the value.

    @[simp]
    theorem List.foldrM_subtype {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] {p : αProp} {l : List { x : α // p x }} {f : { x : α // p x }βm β} {g : αβm β} {x : β} (hf : ∀ (x : α) (h : p x) (b : β), f x, h b = g x b) :
    foldrM f x l = foldrM g x l.unattach

    This lemma identifies monadic folds over lists of subtypes, where the function only depends on the value, not the proposition, and simplifies these to the function directly taking the value.

    @[simp]
    theorem List.mapM_subtype {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] {p : αProp} {l : List { x : α // p x }} {f : { x : α // p x }m β} {g : αm β} (hf : ∀ (x : α) (h : p x), f x, h = g x) :

    This lemma identifies monadic maps over lists of subtypes, where the function only depends on the value, not the proposition, and simplifies these to the function directly taking the value.

    @[simp]
    theorem List.filterMapM_subtype {m : Type u_1 → Type u_2} {α β : Type u_1} [Monad m] [LawfulMonad m] {p : αProp} {l : List { x : α // p x }} {f : { x : α // p x }m (Option β)} {g : αm (Option β)} (hf : ∀ (x : α) (h : p x), f x, h = g x) :
    @[simp]
    theorem List.flatMapM_subtype {m : Type u_1 → Type u_2} {α : Type u_3} {β : Type u_1} [Monad m] [LawfulMonad m] {p : αProp} {l : List { x : α // p x }} {f : { x : α // p x }m (List β)} {g : αm (List β)} (hf : ∀ (x : α) (h : p x), f x, h = g x) :