A core restriction of functional programming is that functions can only use their inputs to calculate their output and thus must always return the same output for a given input. This has the lovely effect that we can reason about what a function does purely by the the types of their inputs and outputs and use that knowledge when refactoring and composing functional programs.
The types are our key to reducing the possibilities of inputs and outputs of our functions. As we reduce the possibilities and weaken what our function can