diff --git a/src/Init/Control/Foldable.lean b/src/Init/Control/Traversable.lean similarity index 57% rename from src/Init/Control/Foldable.lean rename to src/Init/Control/Traversable.lean index ca43ea69df..3ef591c099 100644 --- a/src/Init/Control/Foldable.lean +++ b/src/Init/Control/Traversable.lean @@ -7,14 +7,13 @@ prelude import Init.Core /- - Typeclass for the polymorphic `foldlM` operation described in the paper. + Typeclass for the polymorphic `forM` operation described in the "do unchained" paper. Remark: - `γ` is a "container" type of elements of type `α`. - `α` is treated as an output parameter by the typeclass resolution procedure. That is, it tries to find an instance using only `m` and `γ`. -/ -class Foldable (m : Type u → Type v) (γ : Type w₁) (α : outParam (Type w₂)) where - foldlM [Monad m] : (δ → α → m δ) → δ → γ → m δ +class Traversable (m : Type u → Type v) (γ : Type w₁) (α : outParam (Type w₂)) where + forM [Monad m] : γ → (α → m PUnit) → m PUnit --- Add the alias `foldlM` for `Foldable.foldlM` -export Foldable (foldlM) +export Traversable (forM) diff --git a/src/Init/Data/List/Control.lean b/src/Init/Data/List/Control.lean index fe41f14c07..b1a8101a90 100644 --- a/src/Init/Data/List/Control.lean +++ b/src/Init/Data/List/Control.lean @@ -5,7 +5,7 @@ Author: Leonardo de Moura -/ prelude import Init.Control.Basic -import Init.Control.Foldable +import Init.Control.Traversable import Init.Data.List.Basic namespace List @@ -52,14 +52,16 @@ def mapA {m : Type u → Type v} [Applicative m] {α : Type w} {β : Type u} (f | a::as => List.cons <$> f a <*> mapA f as @[specialize] -def forM {m : Type u → Type v} [Monad m] {α : Type w} (f : α → m PUnit) : List α → m PUnit - | [] => pure ⟨⟩ - | h :: t => do f h; forM f t +protected def forM {m : Type u → Type v} [Monad m] {α : Type w} (as : List α) (f : α → m PUnit) : m PUnit := + match as with + | [] => pure ⟨⟩ + | a :: as => do f a; List.forM as f @[specialize] -def forA {m : Type u → Type v} [Applicative m] {α : Type w} (f : α → m PUnit) : List α → m PUnit - | [] => pure ⟨⟩ - | h :: t => f h *> forA f t +def forA {m : Type u → Type v} [Applicative m] {α : Type w} (as : List α) (f : α → m PUnit) : m PUnit := + match as with + | [] => pure ⟨⟩ + | a :: as => f a *> forA as f @[specialize] def filterAuxM {m : Type → Type v} [Monad m] {α : Type} (f : α → m Bool) : List α → List α → m (List α) @@ -150,14 +152,12 @@ def findSomeM? {m : Type u → Type v} [Monad m] {α : Type w} {β : Type u} (f instance : ForIn m (List α) α where forIn := List.forIn -instance : Foldable m (List α) α where - foldlM := List.foldlM +instance : Traversable m (List α) α where + forM := List.forM --- Add two simplification lemmas for `foldlM` over lists -@[simp] theorem foldlM_nil [Monad m] (f : δ → α → m δ) (d : δ) : foldlM f d ([] : List α) = pure d := +@[simp] theorem forM_nil [Monad m] (f : α → m PUnit) : forM [] f = pure ⟨⟩ := rfl - -@[simp] theorem foldlM_cons [Monad m] (f : δ → α → m δ) (d : δ) (a : α) (as : List α) : foldlM f d (a::as) = f d a >>= fun d => foldlM f d as := +@[simp] theorem forM_cons [Monad m] (f : α → m PUnit) (a : α) (as : List α) : forM (a::as) f = f a >>= fun _ => forM as f := rfl end List diff --git a/src/Init/Data/Range.lean b/src/Init/Data/Range.lean index d1c9c982ac..57b51398bf 100644 --- a/src/Init/Data/Range.lean +++ b/src/Init/Data/Range.lean @@ -5,7 +5,7 @@ Authors: Leonardo de Moura -/ prelude import Init.Meta -import Init.Control.Foldable +import Init.Control.Traversable namespace Std -- We put `Range` in `Init` because we want the notation `[i:j]` without importing `Std` @@ -32,17 +32,17 @@ universes u v instance : ForIn m Range Nat where forIn := Range.forIn -@[inline] protected def foldlM {β : Type u} {m : Type u → Type v} [Monad m] (f : β → Nat → m β) (init : β) (range : Range) : m β := - let rec @[specialize] loop (i : Nat) (j : Nat) (b : β) : m β := do +@[inline] protected def forM {m : Type u → Type v} [Monad m] (range : Range) (f : Nat → m PUnit) : m PUnit := + let rec @[specialize] loop (i : Nat) (j : Nat) : m PUnit := do if j ≥ range.stop then - pure b + pure ⟨⟩ else match i with - | 0 => pure b - | i+1 => loop i (j + range.step) (← f b j) - loop range.stop range.start init + | 0 => pure ⟨⟩ + | i+1 => f j; loop i (j + range.step) + loop range.stop range.start -instance : Foldable m Range Nat where - foldlM := Range.foldlM +instance : Traversable m Range Nat where + forM := Range.forM syntax:max "[" ":" term "]" : term syntax:max "[" term ":" term "]" : term