I am reading in the haskellbook about applicative and trying to understand it.
In the book, the author mentioned:
So, with Applicative, we have
Although this question got a great answer long ago, I would like to add a bit.
Take a look at the following class:
class Functor f => Monoidal f where
unit :: f ()
(**) :: f a -> f b -> f (a, b)
Before explaining why we need some Monoidal
class for a question about Applicative
s, let us first take a look at its laws, abiding by which gives us a monoid:
f a
(x
) is isomorphic to f ((), a)
(unit ** x
), which gives us the left identity. (** unit) :: f a -> f ((), a)
, fmap snd :: f ((), a) -> f a
.f a
(x
) is also isomorphic f (a, ())
(x ** unit
), which gives us the right identity. (unit **) :: f a -> f (a, ())
, fmap fst :: f (a, ()) -> f a
.f ((a, b), c)
((x ** y) ** z
) is isomorphic to f (a, (b, c))
(x ** (y ** z)
), which gives us the associativity. fmap assoc :: f ((a, b), c) -> f (a, (b, c))
, fmap assoc' :: f (a, (b, c)) -> f ((a, b), c)
.As you might have guessed, one can write down Applicative
's methods with Monoidal
's and the other way around:
unit = pure ()
f ** g = (,) <$> f <*> g = liftA2 (,) f g
pure x = const x <$> unit
f <*> g = uncurry id <$> (f ** g)
liftA2 f x y = uncurry f <$> (x ** y)
Moreover, one can prove that Monoidal
and Applicative
laws are telling us the same thing. I asked a question about this a while ago.