# How can I make tuples an instance of this class in Haskell?

`(x,y)`

is already a concrete tuple type, containing two concrete (albeit unknown) types `x`

and `y`

. A functor, or bifunctor, meanwhile is supposed to be *parametric*, i.e. in case of the tuple instance you'd want the contained types to be left open as parameters, which are then filled in with various different concrete types when the methods are used.

I.e., you basically want a *type-level lambda*

```
instance Bifunctor (\x y -> (x, y)) where
```

Well, Haskell doesn't have type-level lambdas, but it does have partial application at the type level – in this case not even *partial*, you don't want to apply the tuple constructor to any types *at all* but simply leave them open. That is written thus:

```
instance Bifunctor (,) where
```

If you wanted to apply it to only one argument, you write

```
instance Functor ((,) a) where
```

which I find easier to understand if parsed as `Functor (a,)`

– but that's not actually legal in Haskell.

Good question.

The class applies to the functor type itself, and in your case the functor type is (,). To get the feeling about it, notice the difference here.

```
:t (,)
(,) :: a -> b -> (a, b)
:t (True,False)
(True,False) :: (Bool, Bool)
```

It would probably have been more intuitive if you had used a Pair type like :

```
data Pair a b = Pair a b
```

Because reading the class definition would have made more obvious the type application of 'p'.

Just like Haskell uses types for values, as illustrated above, it uses types for types (also for compile-time logic), which are named *Kinds*.

```
:k Pair
Pair :: * -> * -> *
:k (,)
(,) :: * -> * -> *
:k (Bool,Bool)
(Bool,Bool) :: *
:k Bifunctor
Bifunctor :: (* -> * -> *) -> Constraint
```

This last line illustrates that Bifunctor class is designed for types of kind `(* -> * -> *)`

, not kind `(*)`

of (a,b), hence the error message you had from GHC.

Your definition was almost right, here is the correct one :

```
instance Bifunctor (,) where
bimap func func' (x, y) = (func x, func' y)
first func (x, y) = (func x, y)
second func (x, y) = (x, func y)
```

**EDIT : illustration of kinds as suggested by @leftroundabout**