Skip to content

Commit 070b6eb

Browse files
hdgarroodth-awake
andauthored
Implement ap in terms of Bind (#229)
Co-authored-by: Thomas Honeyman <[email protected]>
1 parent cfd8711 commit 070b6eb

File tree

3 files changed

+20
-23
lines changed

3 files changed

+20
-23
lines changed

src/Control/Bind.purs

+17-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module Control.Bind
66
, composeKleisli, (>=>)
77
, composeKleisliFlipped, (<=<)
88
, ifM
9+
, ap
910
, module Data.Functor
1011
, module Control.Apply
1112
, module Control.Applicative
@@ -32,10 +33,11 @@ import Data.Unit (Unit)
3233
-- |
3334
-- | where the function argument of `f` is given the name `y`.
3435
-- |
35-
-- | Instances must satisfy the following law in addition to the `Apply`
36+
-- | Instances must satisfy the following laws in addition to the `Apply`
3637
-- | laws:
3738
-- |
3839
-- | - Associativity: `(x >>= f) >>= g = x >>= (\k -> f k >>= g)`
40+
-- | - Apply Superclass: `apply = ap`
3941
-- |
4042
-- | Associativity tells us that we can regroup operations which use `do`
4143
-- | notation so that we can unambiguously write, for example:
@@ -134,3 +136,17 @@ infixr 1 composeKleisliFlipped as <=<
134136
-- | ```
135137
ifM :: forall a m. Bind m => m Boolean -> m a -> m a -> m a
136138
ifM cond t f = cond >>= \cond' -> if cond' then t else f
139+
140+
-- | `ap` provides a default implementation of `(<*>)` for any `Bind`, without
141+
-- | using `(<*>)` as provided by the `Apply`-`Bind` superclass relationship.
142+
-- |
143+
-- | `ap` can therefore be used to write `Apply` instances as follows:
144+
-- |
145+
-- | ```purescript
146+
-- | instance applyF :: Apply F where
147+
-- | apply = ap
148+
-- | ```
149+
ap :: forall m a b. Bind m => m (a -> b) -> m a -> m b
150+
ap f a = do
151+
f' <- f
152+
map f' a

src/Control/Monad.purs

+1-20
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
module Control.Monad
22
( class Monad
33
, liftM1
4-
, ap
54
, whenM
65
, unlessM
76
, module Data.Functor
@@ -12,7 +11,7 @@ module Control.Monad
1211

1312
import Control.Applicative (class Applicative, liftA1, pure, unless, when)
1413
import Control.Apply (class Apply, apply, (*>), (<*), (<*>))
15-
import Control.Bind (class Bind, bind, ifM, join, (<=<), (=<<), (>=>), (>>=))
14+
import Control.Bind (class Bind, bind, ap, ifM, join, (<=<), (=<<), (>=>), (>>=))
1615

1716
import Data.Functor (class Functor, map, void, ($>), (<#>), (<$), (<$>))
1817
import Data.Unit (Unit)
@@ -27,7 +26,6 @@ import Data.Unit (Unit)
2726
-- |
2827
-- | - Left Identity: `pure x >>= f = f x`
2928
-- | - Right Identity: `x >>= pure = x`
30-
-- | - Applicative Superclass: `apply = ap`
3129
class (Applicative m, Bind m) <= Monad m
3230

3331
instance monadFn :: Monad ((->) r)
@@ -50,23 +48,6 @@ liftM1 f a = do
5048
a' <- a
5149
pure (f a')
5250

53-
-- | `ap` provides a default implementation of `(<*>)` for any
54-
-- | [`Monad`](#monad), without using `(<*>)` as provided by the
55-
-- | [`Apply`](#apply)-[`Monad`](#monad) superclass relationship.
56-
-- |
57-
-- | `ap` can therefore be used to write [`Apply`](#apply) instances as
58-
-- | follows:
59-
-- |
60-
-- | ```purescript
61-
-- | instance applyF :: Apply F where
62-
-- | apply = ap
63-
-- | ```
64-
ap :: forall m a b. Monad m => m (a -> b) -> m a -> m b
65-
ap f a = do
66-
f' <- f
67-
a' <- a
68-
pure (f' a')
69-
7051
-- | Perform a monadic action when a condition is true, where the conditional
7152
-- | value is also in a monadic context.
7253
whenM :: forall m. Monad m => m Boolean -> m Unit -> m Unit

src/Prelude.purs

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ module Prelude
3030

3131
import Control.Applicative (class Applicative, pure, liftA1, unless, when)
3232
import Control.Apply (class Apply, apply, (*>), (<*), (<*>))
33-
import Control.Bind (class Bind, bind, class Discard, discard, ifM, join, (<=<), (=<<), (>=>), (>>=))
33+
import Control.Bind (class Bind, bind, class Discard, discard, ifM, ap, join, (<=<), (=<<), (>=>), (>>=))
3434
import Control.Category (class Category, identity)
35-
import Control.Monad (class Monad, ap, liftM1, unlessM, whenM)
35+
import Control.Monad (class Monad, liftM1, unlessM, whenM)
3636
import Control.Semigroupoid (class Semigroupoid, compose, (<<<), (>>>))
3737

3838
import Data.Boolean (otherwise)

0 commit comments

Comments
 (0)