As krappie points out, it's not id (id (id 0)) but ((id id) id) 0. It's not necessary to apply it to a final (non-function) argument: id id id ... does the same (ghci won't like the type of this, use id id id ... id \seq` ()`).

But it doesn't seem to be type-checker either: asking ghci for the types of these expressions is fast.

Yes, nested id is exponential in the same way as nesting pairs within pairs. However, the types are computed rather quickly so it's not inference that's causing the problem; and the types are erased after Core and before assembly, so it's not passing huge type terms around that's the problem (in compiled code). Not clear why exactly this should have the problems it does.

I don't think it's really defaulting. If you put a :t in front of the second one, it also terminates instantly.

I think it's not the top-level type inference that's the problem -- the types are stored in small DAGs for that part -- but in the code generation, which blows the small DAG up into an exponentially sized AST for core. (See e.g. this comment.)

Function application is left associative. So:
id id id 0
is the same as:
(((id id) id) id) 0
If I put the parenthesis this way, I noticed the exact same problem you have. It goes slow as hell once I get to about 20 id's.

If however, you do something more sane, such as:
(id . id . id) 0
or
id (id (id 0))
It goes fast and the problem disappears even with 20 id's.

Upvote because you actually do make a good point. This is a thread about a function that does nothing, applied to itself over and over, and it's got dozens of comments. We've got to be able to laugh at ourselves, right?

But it is possible to learn something from this thread about how a Haskell compiler works. How many things in the world seemed useless when they were discovered, but turned out to be really powerful?

This is really nothing to do with id, it's more to do with how the type checker does its job. It's also something the majority of us have never encountered, nor would anyone actually write anything that looks like the above.

It's an interesting topic though, because it allows people to learn that little bit more about the internals.

Oh, and this is really nothing to do with Haskell either, it's a GHC question.