diff options
author | Baldur Blöndal <baldurpet@gmail.com> | 2019-07-13 16:46:39 +0100 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2019-07-20 07:51:22 -0400 |
commit | 08ad7ef4d26d40f94ba01fdbcadc5c50aeba8ad8 (patch) | |
tree | 29848f92d1be9034f5cd42c8aa5655d8be95b1fe | |
parent | ff996555b97f18d27f82a53c0a9bb32203cb8819 (diff) | |
download | haskell-08ad7ef4d26d40f94ba01fdbcadc5c50aeba8ad8.tar.gz |
Added do-notation examples for Functor, Applicative and Monad combinators.
-rw-r--r-- | libraries/base/Control/Monad.hs | 32 | ||||
-rw-r--r-- | libraries/base/Data/Functor.hs | 21 | ||||
-rw-r--r-- | libraries/base/Data/Void.hs | 10 | ||||
-rw-r--r-- | libraries/base/GHC/Base.hs | 116 |
4 files changed, 179 insertions, 0 deletions
diff --git a/libraries/base/Control/Monad.hs b/libraries/base/Control/Monad.hs index 3faf3b1f8b..c906014cd0 100644 --- a/libraries/base/Control/Monad.hs +++ b/libraries/base/Control/Monad.hs @@ -142,6 +142,13 @@ filterM p = foldr (\ x -> liftA2 (\ flg -> if flg then (x:) else id) (p x infixr 1 <=<, >=> -- | Left-to-right composition of Kleisli arrows. +-- +-- \'@(bs '>=>' cs) a@\' can be understood as the @do@ expression +-- +-- @ +-- do b <- bs a +-- cs b +-- @ (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c) f >=> g = \x -> f x >>= g @@ -157,6 +164,17 @@ f >=> g = \x -> f x >>= g -- | Repeat an action indefinitely. -- +-- Using @ApplicativeDo@: \'@'forever' as@\' can be understood as the +-- pseudo-@do@ expression +-- +-- @ +-- do as +-- as +-- .. +-- @ +-- +-- with @as@ repeating. +-- -- ==== __Examples__ -- -- A common use of 'forever' is to process input from network sockets, @@ -268,6 +286,20 @@ Core: https://gitlab.haskell.org/ghc/ghc/issues/11795#note_118976 -- | @'replicateM' n act@ performs the action @n@ times, -- gathering the results. +-- +-- Using @ApplicativeDo@: \'@'replicateM' 5 as@\' can be understood as +-- the @do@ expression +-- +-- @ +-- do a1 <- as +-- a2 <- as +-- a3 <- as +-- a4 <- as +-- a5 <- as +-- pure [a1,a2,a3,a4,a5] +-- @ +-- +-- Note the @Applicative@ constraint. replicateM :: (Applicative m) => Int -> m a -> m [a] {-# INLINABLE replicateM #-} {-# SPECIALISE replicateM :: Int -> IO a -> IO [a] #-} diff --git a/libraries/base/Data/Functor.hs b/libraries/base/Data/Functor.hs index 0862821124..e48c19e080 100644 --- a/libraries/base/Data/Functor.hs +++ b/libraries/base/Data/Functor.hs @@ -125,6 +125,16 @@ infixl 1 <&> -- | Flipped version of '<$'. -- +-- Using @ApplicativeDo@: \'@as '$>' b@\' can be understood as the +-- @do@ expression +-- +-- @ +-- do as +-- pure b +-- @ +-- +-- with an inferred @Functor@ constraint. +-- -- @since 4.7.0.0 -- -- ==== __Examples__ @@ -162,6 +172,17 @@ infixl 1 <&> -- | @'void' value@ discards or ignores the result of evaluation, such -- as the return value of an 'System.IO.IO' action. -- +-- +-- Using @ApplicativeDo@: \'@'void' as@\' can be understood as the +-- @do@ expression +-- +-- @ +-- do as +-- pure () +-- @ +-- +-- with an inferred @Functor@ constraint. +-- -- ==== __Examples__ -- -- Replace the contents of a @'Data.Maybe.Maybe' 'Data.Int.Int'@ with unit: diff --git a/libraries/base/Data/Void.hs b/libraries/base/Data/Void.hs index beb6041f62..5c2886889b 100644 --- a/libraries/base/Data/Void.hs +++ b/libraries/base/Data/Void.hs @@ -79,6 +79,16 @@ absurd a = case a of {} -- | If 'Void' is uninhabited then any 'Functor' that holds only -- values of type 'Void' is holding no values. -- +-- Using @ApplicativeDo@: \'@'vacuous' theVoid@\' can be understood as the +-- @do@ expression +-- +-- @ +-- do void <- theVoid +-- pure (absurd void) +-- @ +-- +-- with an inferred @Functor@ constraint. +-- -- @since 4.8.0.0 vacuous :: Functor f => f Void -> f a vacuous = fmap absurd diff --git a/libraries/base/GHC/Base.hs b/libraries/base/GHC/Base.hs index b0160ab460..c365c05182 100644 --- a/libraries/base/GHC/Base.hs +++ b/libraries/base/GHC/Base.hs @@ -457,11 +457,30 @@ the first law, so you need only check that the former condition holds. -} class Functor f where + -- | Using @ApplicativeDo@: \'@'fmap' f as@\' can be understood as + -- the @do@ expression + -- + -- @ + -- do a <- as + -- pure (f a) + -- @ + -- + -- with an inferred @Functor@ constraint. fmap :: (a -> b) -> f a -> f b -- | Replace all locations in the input with the same value. -- The default definition is @'fmap' . 'const'@, but this may be -- overridden with a more efficient version. + -- + -- Using @ApplicativeDo@: \'@a '<$' bs@\' can be understood as the + -- @do@ expression + -- + -- @ + -- do bs + -- pure a + -- @ + -- + -- with an inferred @Functor@ constraint. (<$) :: a -> f b -> f a (<$) = fmap . const @@ -538,6 +557,15 @@ class Functor f => Applicative f where -- -- A few functors support an implementation of '<*>' that is more -- efficient than the default one. + -- + -- Using @ApplicativeDo@: \'@fs '<*>' as@\' can be understood as + -- the @do@ expression + -- + -- @ + -- do f <- fs + -- a <- as + -- pure (f a) + -- @ (<*>) :: f (a -> b) -> f a -> f b (<*>) = liftA2 id @@ -550,10 +578,37 @@ class Functor f => Applicative f where -- -- This became a typeclass method in 4.10.0.0. Prior to that, it was -- a function defined in terms of '<*>' and 'fmap'. + -- + -- Using @ApplicativeDo@: \'@'liftA2' f as bs@\' can be understood + -- as the @do@ expression + -- + -- @ + -- do a <- as + -- b <- bs + -- pure (f a b) + -- @ + liftA2 :: (a -> b -> c) -> f a -> f b -> f c liftA2 f x = (<*>) (fmap f x) -- | Sequence actions, discarding the value of the first argument. + -- + -- \'@as '*>' bs@\' can be understood as the @do@ expression + -- + -- @ + -- do as + -- bs + -- @ + -- + -- This is a tad complicated for our @ApplicativeDo@ extension + -- which will give it a @Monad@ constraint. For an @Applicative@ + -- constraint we write it of the form + -- + -- @ + -- do _ <- as + -- b <- bs + -- pure b + -- @ (*>) :: f a -> f b -> f b a1 *> a2 = (id <$ a1) <*> a2 -- This is essentially the same as liftA2 (flip const), but if the @@ -566,22 +621,61 @@ class Functor f => Applicative f where -- liftA2, it would likely be better to define (*>) using liftA2. -- | Sequence actions, discarding the value of the second argument. + -- + -- Using @ApplicativeDo@: \'@as '<*' bs@\' can be understood as + -- the @do@ expression + -- + -- @ + -- do a <- as + -- bs + -- pure a + -- @ (<*) :: f a -> f b -> f a (<*) = liftA2 const -- | A variant of '<*>' with the arguments reversed. +-- +-- Using @ApplicativeDo@: \'@as '<**>' fs@\' can be understood as the +-- @do@ expression +-- +-- @ +-- do a <- as +-- f <- fs +-- pure (f a) +-- @ (<**>) :: Applicative f => f a -> f (a -> b) -> f b (<**>) = liftA2 (\a f -> f a) -- Don't use $ here, see the note at the top of the page -- | Lift a function to actions. -- This function may be used as a value for `fmap` in a `Functor` instance. +-- +-- | Using @ApplicativeDo@: \'@'liftA' f as@\' can be understood as the +-- @do@ expression +-- +-- +-- @ +-- do a <- as +-- pure (f a) +-- @ +-- +-- with an inferred @Functor@ constraint, weaker than @Applicative@. liftA :: Applicative f => (a -> b) -> f a -> f b liftA f a = pure f <*> a -- Caution: since this may be used for `fmap`, we can't use the obvious -- definition of liftA = fmap. -- | Lift a ternary function to actions. +-- +-- Using @ApplicativeDo@: \'@'liftA3' f as bs cs@\' can be understood +-- as the @do@ expression +-- +-- @ +-- do a <- as +-- b <- bs +-- c <- cs +-- pure (f a b c) +-- @ liftA3 :: Applicative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d liftA3 f a b c = liftA2 f a b <*> c @@ -598,6 +692,14 @@ liftA3 f a b c = liftA2 f a b <*> c -- is used to remove one level of monadic structure, projecting its -- bound argument into the outer level. -- +-- +-- \'@'join' bss@\' can be understood as the @do@ expression +-- +-- @ +-- do bs <- bss +-- bs +-- @ +-- -- ==== __Examples__ -- -- A common use of 'join' is to run an 'IO' computation returned from @@ -658,11 +760,25 @@ defined in the "Prelude" satisfy these laws. class Applicative m => Monad m where -- | Sequentially compose two actions, passing any value produced -- by the first as an argument to the second. + -- + -- \'@as '>>=' bs@\' can be understood as the @do@ expression + -- + -- @ + -- do a <- as + -- bs a + -- @ (>>=) :: forall a b. m a -> (a -> m b) -> m b -- | Sequentially compose two actions, discarding any value produced -- by the first, like sequencing operators (such as the semicolon) -- in imperative languages. + -- + -- \'@as '>>' bs@\' can be understood as the @do@ expression + -- + -- @ + -- do as + -- bs + -- @ (>>) :: forall a b. m a -> m b -> m b m >> k = m >>= \_ -> k -- See Note [Recursive bindings for Applicative/Monad] {-# INLINE (>>) #-} |