import Control.Applicative
main = print $ fmap (*2) (1,2)
produces (1,4). I would expect it it to produce (2,4) but inst
Pairs are, essentially, defined like this:
data (,) a b = (,) a b
The Functor class looks like this:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Since the types of function arguments and results must have kind * (i.e. they represent values rather than type functions that can be applied further or more exotic things), we must have a :: *, b :: *, and, most importantly for our purposes, f :: * -> *. Since (,) has kind * -> * -> *, it must be applied to a type of kind * to obtain a type suitable to be a Functor. Thus
instance Functor ((,) x) where
-- fmap :: (a -> b) -> (x,a) -> (x,b)
So there's actually no way to write a Functor instance doing anything else.
One useful class that offers more ways to work with pairs is Bifunctor, from Data.Bifunctor.
class Bifunctor f where
bimap :: (a -> b) -> (c -> d) -> f a c -> f b d
bimap f g = first f . second g
first :: (a -> b) -> f a y -> f b y
first f = bimap f id
second :: (c -> d) -> f x c -> f x d
second g = bimap id g
This lets you write things like the following (from Data.Bifunctor.Join):
newtype Join p a =
Join { runJoin :: p a a }
instance Bifunctor p => Functor (Join p) where
fmap f = Join . bimap f f . runJoin
Join (,) is then essentially the same as Pair, where
data Pair a = Pair a a
Of course, you can also just use the Bifunctor instance to work with pairs directly.