Сначала ответы
Кто-то сказал: «У нас нет объектов, но у нас есть функции более высокого порядка». Заменяют ли функции высшего порядка объекты?
Если вы имеете в виду, могут ли функции более высокого порядка содержать скрытое состояние, тогда да. Функции, определенные внутри других функций, могут захватывать некоторую информацию из своей области и, если она будет возвращена во внешний мир, сохранят эту информацию. Вот что такое замыкания.
Если вы имеете в виду, могут ли функции более высокого порядка содержать изменяемое состояние, то нет. В чистом функциональном программировании они не сохраняют состояние. Они дают одинаковые результаты на тех же входах. Если вы хотите смоделировать, как что-то меняется, вы не перезаписываете переменную, а определяете, как рассчитать ее новое значение из старого.
Конечно, есть ярлыки, и даже функциональные языки позволяют писать в императивном стиле.
Если я попытаюсь сделать это в функциональном программировании, понадобится ли мне много функций более высокого порядка?
Вы собираетесь их часто использовать. Вероятно, даже не думая, что ваши функции более высокого порядка. И, вероятно, наслаждаюсь ими много. Вы просто передадите функции как значения другим функциям.
Например, map
- это HOF. Его первый аргумент - другая функция. То, что вы считаете в императивном языке циклом «для каждого элемента в коллекции: примените некоторую функцию, сохраните результат», на функциональном языке будет «отобразить функцию на коллекцию и получить новую коллекцию результатов». , Складки являются еще одним примером HOF. Таким образом, большинство циклов императивного языка могут быть переведены на вызовы функций более высокого порядка на функциональном языке. Это должно дать понять, как часто вы можете их использовать.
обзор, но очень сложный в функциональном программировании
Это хорошее место для начала: Функциональное программирование .
Пример инкапсуляции "состояния":
f = let x = 3
in let withX y = x + y
in withX
Теперь f
- это то же самое, что и withX
, функция, которая «запоминает», что x = 3
. Когда мы используем f
, нам нужно предоставить только один аргумент, y
, и он будет суммировать его с "запомненным" значением x
(3).
Это должно вывести 3
, а затем [4, 5, 6]
:
main = do
print $ f 0
print $ map f [1..3]
Мы не передаем 3
в качестве аргумента f
, он "запоминает" 3
из закрытия выше,
и мы можем передать f
в качестве параметра map
, который в данном случае является HOF.
Таким образом, функции могут инкапсулировать состояние.
Пример "изменения" переменной
Как я уже говорил выше, в функциональном программировании состояние не является изменяемым. Так, если вы хотите, скажем, применить к значению операцию f
, сохранить результат, а затем применить операцию g
, на функциональном языке вы бы выразили ее с помощью промежуточной переменной, которая содержит результат применения f
и затем примените g
к нему, чтобы вычислить новое значение. Обратите внимание, что вы не «перезаписываете» исходное значение x0
:
applyTwo first second x0 =
let x1 = first x0
in second x1
Но на самом деле его можно написать короче, потому что это просто набор функций:
applyTwo' f g = g . f
Или вы можете обобщить этот подход и написать функцию, которая будет применять любое количество функций:
applyAll [] = id -- don't do anything if there are no functions to apply
applyAll (f:otherFs) = applyAll otherFs . f
Обратите внимание, что applyTwo
и applyAll
теперь являются функциями более высокого порядка. Конечно, они не заменяют объекты, но позволяют избежать изменяемого состояния.
Вот как они используются:
ghci> applyTwo (+1) (*10) 2
30
ghci> applyAll [(+1), (*10)] 2
30