>>> Ap (Just [1, 2, 3]) <> Ap Nothing Ap {getAp = Nothing}
>>> Ap [Sum 10, Sum 20] <> Ap [Sum 1, Sum 2] Ap {getAp = [Sum {getSum = 11},Sum {getSum = 12},Sum {getSum = 21},Sum {getSum = 22}]}
>>> let fn = "hello_world" >>> in writeFile fn "hello" >> appendFile fn " world!" >> (readFile fn >>= putStrLn) "hello world!"
>>> let fn = "foo"; output = readFile' fn >>= putStrLn >>> in output >> appendFile fn (show [1,2,3]) >> output this is what's in the file this is what's in the file[1,2,3]
>>> map (\x -> applyWhen (odd x) (*2) x) [1..10] [2,2,6,4,10,6,14,8,18,10]
>>> map (\x -> applyWhen (length x > 6) ((++ "...") . take 3) x) ["Hi!", "This is amazing", "Hope you're doing well today!", ":D"] ["Hi!","Thi...","Hop...",":D"]
>>> appendList (1 :| [2,3]) [] 1 :| [2,3]
>>> appendList (1 :| [2,3]) [4,5] 1 :| [2,3,4,5]
(<*>) = liftA2 id
liftA2 f x y = f <$> x <*> yFurther, any definition must satisfy the following:
pure id <*> v = v
pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
pure f <*> pure x = pure (f x)
u <*> pure y = pure ($ y) <*> u
forall x y. p (q x y) = f x . g yit follows from the above that
liftA2 p (liftA2 q u v) = liftA2 f u . liftA2 g vIf f is also a Monad, it should satisfy (which implies that pure and <*> satisfy the applicative functor laws).
typeRep @(Maybe Int) === App (typeRep @Maybe) (typeRep @Int)Note that this will also match a function type,
typeRep @(Int# -> Char) === App (App arrow (typeRep @Int#)) (typeRep @Char)where arrow :: TypeRep ((->) :: TYPE IntRep -> Type -> Type).
>>> concatMap (take 3) [[1..], [10..], [100..], [1000..]] [1,2,3,10,11,12,100,101,102,1000,1001,1002]
>>> concatMap (take 3) (Just [1..]) [1,2,3]
>>> fmap show Nothing Nothing >>> fmap show (Just 3) Just "3"Convert from an Either Int Int to an Either Int String using show:
>>> fmap show (Left 17) Left 17 >>> fmap show (Right 17) Right "17"Double each element of a list:
>>> fmap (*2) [1,2,3] [2,4,6]Apply even to the second element of a pair:
>>> fmap even (2,2) (2,True)It may seem surprising that the function is only applied to the last element of the tuple compared to the list example above which applies it to every element in the list. To understand, remember that tuples are type constructors with multiple type parameters: a tuple of 3 elements (a,b,c) can also be written (,,) a b c and its Functor instance is defined for Functor ((,,) a b) (i.e., only the third parameter is free to be mapped over with fmap). It explains why fmap can be used with tuples containing values of different types as in the following example:
>>> fmap even ("hello", 1.0, 4) ("hello",1.0,True)
>>> foldMap Sum [1, 3, 5] Sum {getSum = 9}
>>> foldMap Product [1, 3, 5] Product {getProduct = 15}
>>> foldMap (replicate 3) [1, 2, 3] [1,1,1,2,2,2,3,3,3]When a Monoid's (<>) is lazy in its second argument, foldMap can return a result even from an unbounded structure. For example, lazy accumulation enables Data.ByteString.Builder to efficiently serialise large data structures and produce the output incrementally:
>>> import qualified Data.ByteString.Lazy as L >>> import qualified Data.ByteString.Builder as B >>> let bld :: Int -> B.Builder; bld i = B.intDec i <> B.word8 0x20 >>> let lbs = B.toLazyByteString $ foldMap bld [0..] >>> L.take 64 lbs "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24"
map f [x1, x2, ..., xn] == [f x1, f x2, ..., f xn] map f [x1, x2, ...] == [f x1, f x2, ...]this means that map id == id
>>> map (+1) [1, 2, 3] [2,3,4]
>>> map id [1, 2, 3] [1,2,3]
>>> map (\n -> 3 * n + 1) [1, 2, 3] [4,7,10]