You’re hitting the value restriction, check the manual’s chapter on weak polymorphism.
For short, the compiler assumes that the return value of Fun.id foo
could hide mutation effects, which would make the more general type unsound, so it uses a weaker kind of type variables that can’t generalize. This looks a bit funny for obviously pure functions, but that can’t be tracked without complicating the type system.
Adding a parameter for bar
fixes this because that turns it back into a function definition, which visibly delays the call to Fun.id foo
and thus can’t leak polymorphic values across calls. In other words, knowing you come from Haskell: eta-expansion delays side effects.