В прошлой статье я написал основные причины функционального программирования и объяснил основные причины ажиотажа вокруг функционального программирования в последние несколько лет. В этой статье я собираюсь формализовать некоторые основные понятия функционального программирования:
Функции
Может показаться очевидным начать с функций, учитывая название парадигмы (функционал), в функциональном программировании функции больше похожи на математические функции, и мы можем делать много вещей с функциями, такими как функции карты, хранить функции в списках, составлять функции. , объединить их и многое другое. И вообще, в функциональном программировании нам нужны функции только для получения чего-то похожего на операторы if или логические типы.
Начнем с простых функций:
add3 x = x+3
add3 — это функция, которая принимает числовое значение x и суммирует с ним 3.
add3 3 --outputs: 6 = (3+3) add3 0 --outputs: 3 = (0+3) add3 (-3) --outputs: 0 = (-3+3)
до сих пор ничего, что действительно выходит за рамки базового определения математической функции, поэтому давайте добавим немного специй к нашим функциям:
applyFn f v = f v
Теперь у нас есть функция, которая получает функцию в параметре f и значение в параметре v и возвращает f, вызванную с помощью v:
applyFn add3 3 --outputs 6 (applyFn = add3 3) applyFn (\x -> x+2) 3 --outputs 5
В предыдущем примере кода мы представили две концепции функций, первая — это функции высокого порядка, которые состоят из передачи функций в качестве параметров и их использования для создания нашего конечного результата.
Вторая введенная концепция — это лямбда-функция (\x -> x+2). call 'applyFn (\x -> x+2) 3' x заменяется на 3, а затем к трем добавляется 2, в результате получается 5.
В математике мы можем составлять такие функции, как:
f(x) = x + 2 g(x) = x * 2 + 1 and suppose our x is 5 g ∘ f f will be executed first so: x + 2 -> 5 + 2 -> 7 then g will be called with our final result from f that is 7 x * 2 + 1 -> 7 * 2 + 1 -> 14 + 1 -> 15 generating a final output of: 15
В функциональном языке, таком как haskell, создание функций будет очень похоже на то, как мы это делаем в математике:
f x = x + 2 g x = x * 2 + 1 g . f 5 g (f 5) g 7 15 very similar to mathematics, haskell does a great job getting this mathematical correctness
Но мы также можем выполнять множество вызовов функций для нескольких входов, сохраняя функции в списках и обрабатывая список следующим образом:
[add3, (*2)] <*> [2,3] -- outputs: [5,6,4,6]
Давайте разобьем фрагмент кода выше на:
‘[add3, (*2)]’ список, содержащий функции, нашу предыдущую функцию add3 и арифметическую функцию, которая принимает числовое значение и умножает его на 2.
'‹*›' символ применения в контексте аппликативов. Я не буду здесь вдаваться в подробности абстрактной математики аппликативов, но сейчас рассмотрим символ применения как нечто, что принимает список функций и применяет каждую функцию ко всем значения в списке чисел, возвращающие список всех значений, примененных ко всем функциям в первом списке
‘[2, 3]’ обычный список числовых значений
А теперь процесс вывода:
[add3, (*2)] <*> [2, 3] [add3 2, add3 3] = [5, 6] [(2*2), (3*2)] = [4, 6] [5,6] ++(concatenation) [4,6] [5,6,4,6]
Функции в функциональных языках предлагают нам гораздо больше возможностей, так как функции в функциональном программировании считаются гражданами первого класса, поэтому я надеюсь, что вам будет любопытно искать другие подходы к функциям, но для этой статьи я думаю, что приложения выше хороший пример того, насколько мощными и составными являются функции и как функции буквально являются ядром парадигмы.
Я надеюсь, что читателю было нетрудно усвоить концепцию, и я надеюсь, что читатель смог понять примеры и объяснение функций, и снова функции — это только наша первая концепция в этом путешествии по функциональному программированию, и я также надеюсь получить читатель любопытен и жаждет узнать больше о функциональном программировании. Спасибо, что дочитали до этого места, и увидимся в следующих статьях, где мы продолжим больше говорить о концепциях функционального программирования.