Applicative is a Monoidal Functor :
mappend :: f -> f -> f
$ :: (a -> b) -> a -> b
<*> :: f(a -> b) -> f a -> f b
But I don't see any reference about Monoid in the definition of the Applicative typeclass, could you tell me why ?
Definition :
class Functor f => Applicative (f :: * -> *) where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
GHC.Base.liftA2 :: (a -> b -> c) -> f a -> f b -> f c
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
{-# MINIMAL pure, ((<*>) | liftA2) #-}
No mention of that structural Monoid is provided in this definition, but when you do
> ("ab",(+1)) <*> ("cd", 5)
>("abcd", 6)
You can clearly see the use of a Structural Monoid "(,) String" when implementing this instance of Applicative.
Another example to show that a "Structural Monoid" is used :
Prelude Data.Monoid> (2::Integer,(+1)) <*> (1::Integer,5)
<interactive>:35:1: error:
• Could not deduce (Monoid Integer) arising from a use of ‘<*>’
from the context: Num b
bound by the inferred type of it :: Num b => (Integer, b)
at <interactive>:35:1-36
• In the expression: (2 :: Integer, (+ 1)) <*> (1 :: Integer, 5)
In an equation for ‘it’:
it = (2 :: Integer, (+ 1)) <*> (1 :: Integer, 5)
The Functor typeclass represents the mathematical functor: a mapping between categories in the context of category theory. In practice a functor represents a type that can be mapped over.
Applicative functors are the programming equivalent of lax monoidal functors with tensorial strength in category theory. Applicative functors were introduced in 2008 by Conor McBride and Ross Paterson in their paper Applicative programming with effects.
A small category with a single object is the same thing as a monoid: the morphisms of a one-object category can be thought of as elements of the monoid, and composition in the category is thought of as the monoid operation. Functors between one-object categories correspond to monoid homomorphisms.
Functor in Haskell is a kind of functional representation of different Types which can be mapped over. It is a high level concept of implementing polymorphism. According to Haskell developers, all the Types such as List, Map, Tree, etc. are the instance of the Haskell Functor.
The monoid that's referred to with “monoidal functor” is not a Monoid
monoid, i.e. a value-level monoid. It's a type-level monoid instead. Namely, the boring product monoid
type Mempty = ()
type a <> b = (a,b)
(You may notice that this is not strictly speaking a monoid; it's only if you consider ((a,b),c)
and (a,(b,c))
as the same type. They are sure enough isomorphic.)
To see what this has to do with Applicative
, resp. monoidal functors, we need to write the class in other terms.
class Functor f => Monoidal f where
pureUnit :: f Mempty
fzip :: f a -> f b -> f (a<>b)
-- an even more “general nonsense”, equivalent formulation is
-- upure :: Mempty -> f Mempty
-- fzipt :: (f a<>f b) -> f (a<>b)
-- i.e. the functor maps a monoid to a monoid (in this case the same monoid).
-- That's really the mathematical idea behind this all.
IOW
class Functor f => Monoidal f where
pureUnit :: f ()
fzip :: f a -> f b -> f (a,b)
It's a simple exercise to define a generic instance of the standard Applicative
class in terms of Monoidal
, vice versa.
Regarding ("ab",(+1)) <*> ("cd", 5)
: that doesn't have much to do with Applicative
in general, but only with the writer applicative specifically. The instance is
instance Monoid a => Monoidal ((,) a) where
pureUnit = (mempty, ())
fzip (p,a) (q,b) = (p<>q, (a,b))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With