One of the central tenets of software engineering is that of early error discovery. Many programming languages support this idea with a type system. Roughly speaking, a type is a name for a collection of syntactic values, and a type system encourages the programmer to think about the type of the value that each phrase in the program produces.
Types are names for sets of syntactic values.
The former only accepts numbers, while the latter must receive a function value in the first position. While this is not all that we would like to be able to say, this is all we can say in our current type framework. For instance, it would be useful to be able to specify what type of argument a procedure can accept. Once we have names for sets of values, we can try to determine to which set the result of an expression belongs and see whether this result makes sense in the given context. I'll tell you what the type of the expression is.