Any system can be thought of as having two parts: a specification and an implementation. The specification is a contract. The contract defines how the system should behave. We say a system is correct if the actual behavior of the system is in accord with the contract. If the system behaves differently, then we say it fails.
The specification defines how the rest of the world interacts with the system, as seen from the outside. The implementation is how the system is constructed, as seen from the inside. The specification is usually much simpler to understand than the implementation.
This means that it is possible to build a system as a concentric series of layers. Once can proceed step by step, building layer upon layer. At each layer, build an implementation that takes the next lower specification and provides the next higher one. It is not necessary to understand everything at once.
There are three properties a system should have to support the principle of abstraction.
Encapsulation
It should be possible to hide the internals of a part.
Compositionality
It should be possible to combine parts to make a new part.
Instantiation/Invocation
It should be possible to create many instances of a part based on a single definition. These instances plug themselves into their environment (the rest of the system in which they will live) when they are created.
Lexical scoping supports encapsulation and higher order programming supports instantiation. The properties do not require state; they can be used in declarative programming as well. For example, encapsulation is orthogonal to state. On the one hand, it is possible to use encapsulation in declarative programs without state.