This is probably a very basic question, but ...
A function that\'s defined as, say
foo :: a -> Integer
denotes a function from <
It's a feature, and actually is very fundamental. It boils down to a property known as parametricity in programming language theory. Roughly, that means that evaluation should never depend on types that are variables at compile time. You cannot look at a value where you do not know its concrete type statically.
Why is that good? It gives much stronger invariants about programs. For example, you know from the type alone that a -> a
has to be the identity function (or diverges). Similar "free theorems" apply to many other polymorphic functions. Parametricity also is the basis for more advanced type-based abstraction techniques. For example, the type ST s a
in Haskell (the state monad), and the type of the corresponding runST
function, rely on s
being parametric. That ensures that the running function has no way of messing with the internal representation of the state.
It is also important for efficient implementation. A program does not have to pass around costly type information at run time (type erasure), and the compiler can choose overlapping representations for different types. As an example of the latter, 0 and False and () and [] are all represented by 0 at runtime. This wouldn't be possible if a function like yours was allowed.