id
is supposed to be the identity morphism for any given Haskell type. The identify morphism for a type A in Hask is a function of type A -> A
, but it's not just any function of type A -> A
; it has to obey the category laws.
In particular, it must be a left and right identity for composition with morphisms to/from the object A. If idA
is the identify morphism for the object A, this means for any object B and morphism f :: A -> B
, f . idA
must be exactly the same as f
, and for any object C and morphism g :: C -> A
, ifA . g
must be exactly the same as g
.
We can test your claim that any function of type A -> A
can be A's identity, by picking a concrete case. Lets take take (+1) :: Integer -> Integer
as the identity for Integer, and consider the function (*2) :: Integer -> Integer
. Now obviously (*2) . (+1)
, (+1) . (*2)
, and just (*2)
are all the same, so we've shown - oh wait, those are not the same function at all.
Note I have not brought in equality of Haskell values here. I'm talking about equality of the morphisms in the Hask category; and equality of morphisms most certainly is within the domain of category theory, since without it the category laws about the identity morphism are meaningless.
A key point which I was confused about at one point is that although it doesn't make sense to consider two different objects with the same type (since the objects are types when we're talking about Hask), you can have two different morphisms with the same type. Category theory does allow there to be several different morphisms between two objects A and B (and does allow there to be morphisms from an object to itself which are not identity morphisms, and are distinguished from each other). Morphisms are not purely defined by their "endpoints".
The identity laws are actually pretty strict requirements, and should heavily hint that not just any old A -> A
function will do for idA
. There's a clear intuition that to be able to compose with arbitrary other morphisms without changing them, the identity morphism needs to "do nothing" (whatever that means for the category in question).
In Hask where we know morphisms are functions, there's a pretty obvious interpretation of "do nothing"; the function that just returns its input. It should be clear that this does work for the category laws:
f . id = f
id . f = f
And also, if a proposed identity morphism that does anything other than return its input unchanged (there exists some x
such that badId x
is not x
), then you can disprove the category laws by trying to compose with id
!
(badId . id) x
badId (id x)
badId x
badId x
is not x
, by assumption, so badId . id
can't be equal to id
(which is defined by id x = x
). So badId
isn't a left identity for composition.