Remark: we can define mapM
, mapM₂
and forM
using Applicative
instead of Monad
.
Example:
def mapM {m : Type u → Type v} [Applicative m] {α : Type w} {β : Type u} (f : α → m β) : List α → m (List β)
| [] => pure []
| a::as => List.cons <$> (f a) <*> mapM as
However, we consider f <$> a <*> b
an anti-idiom because the generated code
may produce unnecessary closure allocations.
Suppose m
is a Monad
, and it uses the default implementation for Applicative.seq
.
Then, the compiler expands f <$> a <*> b <*> c
into something equivalent to
(Functor.map f a >>= fun g_1 => Functor.map g_1 b) >>= fun g_2 => Functor.map g_2 c
In an ideal world, the compiler may eliminate the temporary closures g_1
and g_2
after it inlines
Functor.map
and Monad.bind
. However, this can easily fail. For example, suppose
Functor.map f a >>= fun g_1 => Functor.map g_1 b
expanded into a match-expression.
This is not unreasonable and can happen in many different ways, e.g., we are using a monad that
may throw exceptions. Then, the compiler has to decide whether it will create a join-point for
the continuation of the match or float it. If the compiler decides to float, then it will
be able to eliminate the closures, but it may not be feasible since floating match expressions
may produce exponential blowup in the code size.
Finally, we rarely use mapM
with something that is not a Monad
.
Users that want to use mapM
with Applicative
should use mapA
instead.
Applies the monadic action f
on every element in the list, left-to-right, and returns the list of
results.
See List.forM
for the variant that discards the results.
See List.mapA
for the variant that works with Applicative
.
Equations
- List.mapM f as = List.mapM.loop f as []
Instances For
Equations
- List.mapM.loop f [] x = pure x.reverse
- List.mapM.loop f (a :: as) x = do let __do_lift ← f a List.mapM.loop f as (__do_lift :: x)
Instances For
Applies the applicative action f
on every element in the list, left-to-right, and returns the list of
results.
NB: If m
is also a Monad
, then using mapM
can be more efficient.
See List.forA
for the variant that discards the results.
See List.mapM
for the variant that works with Monad
.
Warning: this function is not tail-recursive, meaning that it may fail with a stack overflow on long lists.
Instances For
Applies the monadic action f
on every element in the list, left-to-right.
See List.mapM
for the variant that collects results.
See List.forA
for the variant that works with Applicative
.
Equations
- [].forM f = pure PUnit.unit
- (a :: as_1).forM f = do f a as_1.forM f
Instances For
Applies the applicative action f
on every element in the list, left-to-right.
NB: If m
is also a Monad
, then using forM
can be more efficient.
See List.mapA
for the variant that collects results.
See List.forM
for the variant that works with Monad
.
Equations
- [].forA f = pure PUnit.unit
- (a :: as_1).forA f = f a *> as_1.forA f
Instances For
Equations
- List.filterAuxM f [] x = pure x
- List.filterAuxM f (h :: t) x = do let b ← f h List.filterAuxM f t (bif b then h :: x else x)
Instances For
Applies the monadic function f
on every element x
in the list, left-to-right, and returns those
results y
for which f x
returns some y
.
Equations
- List.filterMapM f as = List.filterMapM.loop f as []
Instances For
Equations
- List.filterMapM.loop f [] x = pure x.reverse
- List.filterMapM.loop f (a :: as) x = do let __do_lift ← f a match __do_lift with | none => List.filterMapM.loop f as x | some b => List.filterMapM.loop f as (b :: x)
Instances For
Folds a monadic function over a list from left to right:
foldlM f x₀ [a, b, c] = do
let x₁ ← f x₀ a
let x₂ ← f x₁ b
let x₃ ← f x₂ c
pure x₃
Equations
- List.foldlM x✝ x [] = pure x
- List.foldlM x✝ x (a :: as) = do let s' ← x✝ x a List.foldlM x✝ s' as
Instances For
Folds a monadic function over a list from right to left:
foldrM f x₀ [a, b, c] = do
let x₁ ← f c x₀
let x₂ ← f b x₁
let x₃ ← f a x₂
pure x₃
Equations
- List.foldrM f init l = List.foldlM (fun (s : s) (a : α) => f a s) init l.reverse
Instances For
Maps f
over the list and collects the results with <|>
.
firstM f [a, b, c] = f a <|> f b <|> f c <|> failure
Equations
- List.firstM f [] = failure
- List.firstM f (a :: as) = (f a <|> List.firstM f as)
Instances For
Equations
- List.findM? p [] = pure none
- List.findM? p (a :: as) = do let __do_lift ← p a match __do_lift with | true => pure (some a) | false => List.findM? p as
Instances For
Equations
- List.findSomeM? f [] = pure none
- List.findSomeM? f (a :: as) = do let __do_lift ← f a match __do_lift with | some b => pure (some b) | none => List.findSomeM? f as
Instances For
Equations
- One or more equations did not get rendered due to their size.
- List.forIn'.loop as f [] x x_3 = pure x
Instances For
Equations
- List.instFunctor = { map := fun {α β : Type ?u.10} => List.map, mapConst := fun {α β : Type ?u.10} => List.map ∘ Function.const β }