+module Apexamples where
+
+import Control.Applicative
+
+pair :: Applicative f => f a -> f b -> f (a,b)
+-- pair fa fb = (\x y -> (x,y)) <$> fa <*> fb
+-- pair fa fb = (,) <$> fa <*> fb
+-- pair fa fb = liftA2 (,) fa fb
+pair = liftA2 (,)
+
+
+{-| Can you implement the following functions?
+
+Consider what each function does when f is replaced with each of the types:
+
+
+f = Maybe: the result is Nothing if either of the arguments is; if both are
+ Just the result is Just their pairing.
+f = []: pair computes the Cartesian product of two lists.
+f = ZipList: pair is the same as the standard zip function.
+f = IO: pair runs two IO actions in sequence, returning a pair of their results.
+f = Parser: pair runs two parsers in sequence (the parsers consume consecutive
+ sections of the input), returning their results as a pair. If either parser fails, the whole thing fails.
+
+
+(*>) :: Applicative f => f a -> f b -> f b
+mapA :: Applicative f => (a -> f b) -> ([a] -> f [b])
+sequenceA :: Applicative f => [f a] -> f [a]
+replicateA :: Applicative f => Int -> f a -> f [a]
+
+-}
+
+(*>) :: Applicative f => f a -> f b -> f b
+fa *> fb = (flip const) <$> fa <*> fb
+
+mapA :: Applicative f => (a -> f b) -> ([a] -> f [b])
+mapA _ [] = pure []
+mapA f' (x:xs) = liftA2 (:) (f' x) $ mapA f' xs
+
+sequenceA :: Applicative f => [f a] -> f [a]
+sequenceA [] = pure []
+sequenceA (x:xs) = (:) <$> x <*> sequenceA xs
+-- sequenceA (x:xs) = liftA2 (:) x (sequenceA xs)
+
+replicateA :: Applicative f => Int -> f a -> f [a]
+replicateA n x = sequenceA (replicate n x)