Answers first
Somebody said "we don't have objects, but we have higher order functions". Do higher order functions replace objects?
If you mean can higher order functions contain some hidden state, then yes. Functions defined inside of the other functions can capture some information from their scope, and, if returned to the outer world, will preserve this information. This is what closures are about.
If you mean can higher order functions contain mutable state, then no. In pure functional programming they are not stateful. They produce the same results on the same inputs. If you want to simulate how something changes, you do not overwrite a variable, but you define how to calculate its new value from the old one.
Of course, there are shortcuts, and even functional languages allow for writing in imperative style.
If I try to do that in functional programming, am I going to need lots of higher order functions?
You are going to use them a lot. Probably not even thinking that your functions are higher-order. And probably, enjoying them a lot. You'll just pass functions as values to other functions.
For example, map
is a HOF. Its first argument is another function. What you would think of in an imperative language as a loop "for every element in a collection: apply some function, save the result", in the functional language will be "map a function over a collection and get a new collection of results". Folds are another example of HOFs. So most of the loops from an imperative language can be translated to the calls of a higher order functions in a functional language. This is to make clear how often you are likely to use them.
overview, but very over in functional programming
This is a good place to start: Functional Programming.
An example of encapsulating "state":
f = let x = 3
in let withX y = x + y
in withX
Now f
is the same as withX
, which is a function that "remembers", that x = 3
. When we use f
, we need to supply only one argument, y
, and it will sum it with the "remembered" value of x
(3).
This should print 3
and then [4, 5, 6]
:
main = do
print $ f 0
print $ map f [1..3]
We do not pass 3
as an argument to f
, it "remembers" 3
from the closure above,
and we can pass f
itself as a parameter to map
, which is a HOF in this case.
So functions can encapsulate state.
An example of "changing" a variable
As I said above, in functional programming, the state is not mutable. So if you want to, say, apply operation f
to the value, save the result, and then apply operation g
, in functional language you would express it with an intermediate variable, which contains the result of applying f
, and then apply g
to it to calculate the new value. Please note that you are not "overwriting" the original value x0
:
applyTwo first second x0 =
let x1 = first x0
in second x1
But in fact it is possible to write it shorter, because it is just a simple composition of functions:
applyTwo' f g = g . f
Or you can generalize this approach, and write a function, which will apply any number of functions:
applyAll [] = id -- don't do anything if there are no functions to apply
applyAll (f:otherFs) = applyAll otherFs . f
Please note, that applyTwo
and applyAll
are now a higher order functions. Of course, they do not replace objects, but allow to avoid the mutable state.
This how they are used:
ghci> applyTwo (+1) (*10) 2
30
ghci> applyAll [(+1), (*10)] 2
30