Skip to content

Latest commit

 

History

History
148 lines (112 loc) · 3.26 KB

functions_comprehensible.md

File metadata and controls

148 lines (112 loc) · 3.26 KB

Functions in comprehensible notation

Sequence/mapM

sequence :: Monad m => [m a] -> m [a]

sequence = mapM id

sequence [a, b, ..., c] = do
      x <- a
      y <- b
      ...
      z <- c
      return [x, y, ..., z]
mapM :: Monad m => (a -> m b) -> [a] -> m [b]

mapM f = sequence . map f

mapM f [a, b, ..., c] = do
      x <- f a
      y <- f b
      ...
      z <- f c
      return [x, y, ..., z]

Foldl/foldr

foldr f z xs replaces every (:) in xs with f, and the [] with z. This also explains how foldr (:) [] is the identity on lists: it replaces (:) with (:) and [] with [].

-- (\x acc -> newAcc) -> initialValue -> list -> result
foldr :: (a -> b -> b) -> b -> [a] -> b

foldr f z (x1 : x2 : x3 : ... : []) = x1 `f` (x2 `f` ... (xn `f` z)...))

Graphical version:

  :                            f
 / \                          / \
1   :         foldr f z      1   f
   / \           ==>            / \
  2   :                        2   f
     / \                          / \
    3   :                        3   f
       / \                          / \
      4  []                        4   z
-- (\acc x -> newAcc) -> initialValue -> list -> result
foldl :: (a -> b -> a) -> a -> [b] -> a

foldl f z [x1, x2, ..., xn] == (...((z `f` x1) `f` x2) `f`...) `f` xn
                            == f ( ... (f (f (f (f z x1) x2) x3) x4) ...) xn

Graphical version:

  :                                  f
 / \                                / \
1   :         foldl f z            f   4
   / \           ==>              / \
  2   :                          f   3
     / \                        / \
    3   :                      f   2
       / \                    / \
      4  []                  z   1

foldM, filterM

foldM is like foldl, but the accumulator is monadic.

foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a
foldM f a1 [x1, x2, ..., xm] = do
      a2 <- f a1 x1
      a3 <- f a2 x2
      ...
      f am xm

Another way of seeing it is as a chain of >>=:

foldM f a1 [x1, x2, ..., xm] = let f' = flip f
                               in return a1 >>= f' x1
                                            >>= f' x2
                                            ...
                                            >>= f' xm
filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
filterM _ [] = return []
filterM p (x:xs) = do
      flag <- p x
      ys   <- filterM p xs
      return (if flag then x:ys else ys)

Desugaring do notation

  • A do block with a single action as its content is equivalent to not having the do keyword:.

    do action   ---->   action
  • The <- symbol desugars to a >>= (pronounced »bind«) operator:

    do x <- action   ---->   action >>= \x -> do REST
       REST
  • An action not bound via <- is desugared to the >> operator:

    do action   ---->   action >> do REST
       REST
  • The standalone let in do notation is translated to a let…in… block:

    do let definition = value   ---->   let definition = value in do REST
       REST