lean4-htt/library/init/monad_combinators.lean
Leonardo de Moura 90bfd84a07 feat(frontends/lean): Type is now (Type 1)
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*
2016-09-17 14:30:54 -07:00

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