refactor: Foldable => Traversable

This commit is contained in:
Leonardo de Moura 2021-02-28 16:11:20 -08:00
parent 9234145955
commit 35e1f5ad97
3 changed files with 26 additions and 27 deletions

View file

@ -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)

View file

@ -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

View file

@ -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