softshipper
softshipper

Reputation: 34081

Representation of tuple applicative

I am trying to understand the tuple applicative. When I look at information in prelude about tuple, it says:

instance (Monoid a, Monoid b) => Monoid (a, b)
instance Monoid a => Applicative ((,) a)

What does ((,) a) mean? It does not look like a tuple.

I have following example:

Prelude Data.Monoid> ((Sum 2), (+2)) <*> ((Sum 45), 8)
(Sum {getSum = 47},10)

The first argument in the tuple is an instance of monoid and the second it is just a function application. But how does the signature ((,) a) match the example above?

Upvotes: 1

Views: 1452

Answers (1)

leftaroundabout
leftaroundabout

Reputation: 120711

I prefer to write the instance as a tuple section (which is not actually legal Haskell, but gets the point across:

instance Monoid a => Applicative (a,)

... and before discussing that, consider

instance Functor (a,)

What this does is just: for any left-hand element (of type a), map over whichever right-hand argument there is. I.e.

  fmap :: (b -> c) -> (a,b) -> (a,c)

One might at this point wonder why we have (a,) and not (,a). Well, mathematically speaking, the following is just as valid:

instance Functor (,a)
  fmap :: (a -> b) -> (a,c) -> (b,c)

...however that can't be defined because (a,b) is in fact syntactic sugar for (,) a b, i.e. the tuple-type-constructor (,) applied first to the a type and then to the b type. Now, in instance Functor (a,), we simply leave the b open to be fmapped over, hence

instance Functor ((,) a)

But it's not possible to _only apply the b argument, while leaving a open – that would require a sort of type-level lambda

“instance Functor (\b -> (a,b))”

which is not supported.

Now as to Applicative – that just extends the (a,) functor to also support combinations of multiple tuples, provided there's already a natural way to combine the a elements – that's what the Monoid instance offers. This is better known as the Writer monad, because it's well suited for generating a “operations log” along with the actual computation results:

Prelude> ("4+", (4+)) <*> ("10",10)
("4+10",14)

Upvotes: 3

Related Questions