The lessons behind “id :: a -> a”

Raymond Tay
Sep 5, 2018 · 2 min read

The haskell id function is most mysterious to me when i first started with Haskell because its a function that is most easily overlooked. The type signature of this function is

id :: a -> a

and what it says is “id returns whatever it took” and initially i was like “Huh?”. One of the uses can be found in GHC.Base.hs file (if you were browsing the GHC codebase like i was) which is listed in the join function’s definition:

join :: (Monad m) => m (m a) -> m a
join x = x >>= id

What is cool about this seemingly innocent function is that join uses id to simply return the innermost layer of abstraction.

join :: (Monad m) => m (m a) -> m a
join = do { xx <- x; xx }
-- this is effectively the same as the above.

Considering that join peels away one layer of abstraction, when i compose 2 join s together, i would be able to peel away 2 layers of abstraction and so on so forth. Funny enough that all this power came from id . Just to illustrate why this is possibly the case, let’s go over a simple example:

> join [[1],[2,3]]
> [1,2,3]
nothing extra ordinarily wrong is going on, everything's expected.

Contrast the above with this

> join2 x = do { xx <- x; return x }
> join2 [[1],[2,3]]
-- What is going on?

The main thing you should realise is the difference between abstaining the use of return :: Monad m => a -> m a because it wraps the value and in the situation where everyone knows what join is suppose to do, it would be wrong to use the definition of join2. The semantics of the function we want to write definitely would guide us in knowing whether the function conforms to the desired outcomes we want and the laws of Monads are there to guide us in writing the proper monadic function. How so? Well, the first two laws of Monads (left-identity and right-identity) shows us how to avoid any unnecessary use of return and the last law (i.e. associativity) tells us whether our function can be broken down further and composed together. These 3 monad laws are very important from the perspective of a software engineer since they help us build maintainable and reusable software.

Raymond Tay

Written by

Head of Engineering at Thales Digital Factory, Singapore. Author of 'OpenCL Parallel Programming cookbook' & 'Developing an Akka Edge'.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade