In the standard library, we should use explicit universe variables for universe polymorphic definitions. Users that want to declare universe polymorphic definitions but do not want to provide universe level parameters should use Type _ or Type*
76 lines
2.9 KiB
Text
76 lines
2.9 KiB
Text
/-
|
|
Copyright (c) 2016 Microsoft Corporation. All rights reserved.
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
Authors: Jeremy Avigad
|
|
|
|
Monad combinators, as in Haskell's Control.Monad.
|
|
-/
|
|
prelude
|
|
import init.monad init.list
|
|
set_option new_elaborator true
|
|
namespace monad
|
|
|
|
definition mapM {m : Type → Type} [monad m] {A B : Type} (f : A → m B) : list A → m (list B)
|
|
| [] := return []
|
|
| (h :: t) := do h' ← f h, t' ← mapM t, return (h' :: t')
|
|
|
|
definition mapM' {m : Type → Type} [monad m] {A B : Type} (f : A → m B) : list A → m unit
|
|
| [] := return ()
|
|
| (h :: t) := f h >> mapM' t
|
|
|
|
definition forM {m : Type → Type} [monad m] {A B : Type} (l : list A) (f : A → m B) : m (list B) :=
|
|
mapM f l
|
|
|
|
definition forM' {m : Type → Type} [monad m] {A B : Type} (l : list A) (f : A → m B) : m unit :=
|
|
mapM' f l
|
|
|
|
definition sequence {m : Type → Type} [monad m] {A : Type} : list (m A) → m (list A)
|
|
| [] := return []
|
|
| (h :: t) := do h' ← h, t' ← sequence t, return (h' :: t')
|
|
|
|
definition sequence' {m : Type → Type} [monad m] {A : Type} : list (m A) → m unit
|
|
| [] := return ()
|
|
| (h :: t) := h >> sequence' t
|
|
|
|
infix ` =<< `:2 := λ u v, v >>= u
|
|
|
|
infix ` >=> `:2 := λ s t a, s a >>= t
|
|
|
|
infix ` <=< `:2 := λ t s a, s a >>= t
|
|
|
|
definition join {m : Type → Type} [monad m] {A : Type} (a : m (m A)) : m A :=
|
|
bind a id
|
|
|
|
definition filterM {m : Type → Type} [monad m] {A : Type} (f : A → m bool) : list A → m (list A)
|
|
| [] := return []
|
|
| (h :: t) := do b ← f h, t' ← filterM t, bool.cond b (return (h :: t')) (return t')
|
|
|
|
definition whenb {m : Type → Type} [monad m] (b : bool) (t : m unit) : m unit :=
|
|
bool.cond b t (return ())
|
|
|
|
definition unlessb {m : Type → Type} [monad m] (b : bool) (t : m unit) : m unit :=
|
|
bool.cond b (return ()) t
|
|
|
|
definition condM {m : Type → Type} [monad m] {A : Type} (mbool : m bool)
|
|
(tm fm : m A) : m A :=
|
|
do b ← mbool, bool.cond b tm fm
|
|
|
|
definition liftM {m : Type → Type} [monad m] {A R : Type} (f : A → R) (ma : m A) : m R :=
|
|
do a ← ma, return (f a)
|
|
|
|
definition liftM₂ {m : Type → Type} [monad m] {A R : Type} (f : A → A → R) (ma₁ ma₂: m A) : m R :=
|
|
do a₁ ← ma₁, a₂ ← ma₂, return (f a₁ a₂)
|
|
|
|
definition liftM₃ {m : Type → Type} [monad m] {A R : Type} (f : A → A → A → R)
|
|
(ma₁ ma₂ ma₃ : m A) : m R :=
|
|
do a₁ ← ma₁, a₂ ← ma₂, a₃ ← ma₃, return (f a₁ a₂ a₃)
|
|
|
|
definition liftM₄ {m : Type → Type} [monad m] {A R : Type} (f : A → A → A → A → R)
|
|
(ma₁ ma₂ ma₃ ma₄ : m A) : m R :=
|
|
do a₁ ← ma₁, a₂ ← ma₂, a₃ ← ma₃, a₄ ← ma₄, return (f a₁ a₂ a₃ a₄)
|
|
|
|
definition liftM₅ {m : Type → Type} [monad m] {A R : Type} (f : A → A → A → A → A → R)
|
|
(ma₁ ma₂ ma₃ ma₄ ma₅ : m A) : m R :=
|
|
do a₁ ← ma₁, a₂ ← ma₂, a₃ ← ma₃, a₄ ← ma₄, a₅ ← ma₅, return (f a₁ a₂ a₃ a₄ a₅)
|
|
|
|
end monad
|