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.
Equations
- List.mapM.loop f [] x = pure (List.reverse x)
- List.mapM.loop f (a :: as) x = do let __do_lift ← f a List.mapM.loop f as (__do_lift :: x)
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
Equations
- List.filterM f as = do let as ← List.filterAuxM f as [] pure (List.reverse as)
Instances For
Equations
- List.filterRevM f as = List.filterAuxM f (List.reverse as) []
Instances For
Equations
- List.filterMapM f as = List.filterMapM.loop f (List.reverse as) []
Instances For
Equations
- List.filterMapM.loop f [] x = pure x
- 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
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
Equations
- List.foldrM f init l = List.foldlM (fun (s : s) (a : α) => f a s) init (List.reverse l)
Instances For
Equations
- List.firstM f [] = failure
- List.firstM f (a :: as) = HOrElse.hOrElse (f a) fun (x : Unit) => 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
- List.forIn as init f = List.forIn.loop f as init
Instances For
Equations
- List.forIn.loop f [] x = pure x
- List.forIn.loop f (a :: as) x = do let __do_lift ← f a x match __do_lift with | ForInStep.done b => pure b | ForInStep.yield b => List.forIn.loop f as b
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.instFunctorList = { map := fun {α β : Type u_1} => List.map, mapConst := fun {α β : Type u_1} => List.map ∘ Function.const β }