Является ли функциональное программирование типом декларативного программирования?
Я знаю, что декларативное программирование просто проходит входные данные и ожидает выходных данных без указания процедуры, как это делается. В функциональном программировании - это парадигма программирования, которая принимает входные данные и возвращает выходные данные. Когда я проверил функциональное программирование высшего порядка, мы передали функцию map / lower, которая не раскрывает процедуру, как это делается. Так функциональное программирование высшего и декларативного программирования - это одно и то же?
2 ответа
Краткий ответ: нет.
Википедия определяет декларативное программирование как:
В информатике декларативное программирование - это парадигма программирования - стиль построения структуры и элементов компьютерных программ, - который выражает логику вычислений без описания потока управления.
Или немного смело заявить: "Скажи, что ты хочешь, а не как ты этого хочешь".
Таким образом, это контрастирует с императивными языками программирования, где программа рассматривается как набор инструкций, которые выполняются одна за другой. Дело в том, что map
и т. д. не показывают, что процедура не делает ее декларативной: можно использовать множество библиотек C, которые являются проприетарными и не позволяют вам проверять исходный код. Это, однако, не означает, что они являются декларативными.
Определение функционального программирования с другой стороны:
В компьютерных науках функциональное программирование - это парадигма программирования - стиль построения структуры и элементов компьютерных программ, который рассматривает вычисления как оценку математических функций и избегает изменяющихся состояний и изменчивых данных. Это декларативная парадигма программирования, которая означает, что программирование выполняется с помощью выражений или объявлений вместо операторов.
На основании этих определений можно сказать, что функциональное программирование является подмножеством декларативного программирования. Однако в практическом смысле, если мы будем следовать строгим определениям, ни один язык программирования в настоящее время не является чисто и однозначно декларативным или функциональным. Однако можно сказать, что Haskell более декларативен, чем Java.
Декларативное программирование обычно считается "более безопасным", поскольку у людей, как правило, возникают проблемы с побочными эффектами. Многие ошибки программирования являются результатом того, что не учитываются все побочные эффекты. С другой стороны это трудно
- разработать язык, который позволяет программисту описывать то, что он хочет, не вдаваясь в подробности о том, как это сделать;
- реализовать компилятор, который будет генерировать - на основе таких программ - эффективную реализацию; а также
- Некоторые проблемы имеют свои побочные эффекты. Например, если вы работаете с базой данных, сетевым подключением или файловой системой, то чтение / запись в файл, например, должна иметь побочные эффекты. Можно, конечно, принять решение не делать эту часть языка программирования (например, многие языки программирования с ограничениями не допускают такого типа действий и являются "вспомогательным языком" в более крупной системе).
Было несколько попыток создать такой язык. Наиболее популярными, на мой взгляд, являются логическое программирование, функциональное программирование и программирование с ограничениями. У каждого есть свои достоинства и проблемы. Мы также можем наблюдать этот декларативный подход, например, в базах данных (таких как SQL) и обработке текста /XML (с XSLT, XPath, регулярными выражениями,...), где не указывается, как разрешается запрос, а просто указывается, например, через регулярное выражение, что вы ищете.
Независимо от того, является ли язык программирования декларативным, это немного размытое обсуждение. Хотя языки программирования, языки моделирования и библиотеки, такие как Haskell, Prolog, Gecode,... определенно сделали программирование более декларативным, они, вероятно, не декларативны в самом строгом смысле. В самом строгом смысле следует подумать, что независимо от того, как вы пишете логику, компилятор всегда будет давать один и тот же результат (хотя это может занять немного больше времени).
Скажем, например, мы хотим проверить, является ли список пустым в Haskell. Мы можем написать это так:
is_empty1 :: [a] -> Bool
is_empty1 [] = True
is_empty1 (_:_) = False
Однако мы можем написать это так:
is_empty2 :: [a] -> Bool
is_empty2 l = length l == 0
Оба должны давать одинаковый результат для одинаковых запросов. Однако если мы дадим ему бесконечный список, is_empty1 (repeat 0)
вернусь False
в то время как is_empty2 (repeat 0)
будет цикл навсегда. Таким образом, это означает, что мы каким-то образом все еще ввели некоторый "поток управления" в программу: мы определили - до некоторой степени - как Хаскелл должен оценивать это. Хотя ленивое программирование приведет к тому, что программист не определит, что в первую очередь следует оценивать, все еще существуют спецификации, как Haskell будет это оценивать.
По мнению некоторых людей, это разница между программированием и спецификацией. Один из моих профессоров однажды заявил, что, по его словам, разница в том, что когда вы что-то программируете, вы каким-то образом контролируете, как что-то оценивается, тогда как когда вы что-то указываете, у вас нет контроля. Но опять же, это только одно из многих определений.
Не совсем, функциональное программирование уделяет больше внимания тому, что нужно вычислять, а не как вычислять. Однако в функциональном программировании есть шаблоны, которые в значительной степени представляют собой шаблоны потоков управления, которые вы обычно ассоциируете с декларативным программированием, например, следующий поток управления:
let continue = ref true in
while !continue do
...
if cond then continue := false
else
...
done
Выглядит знакомо, да? Здесь вы можете увидеть некоторые декларативные конструкции, но на этот раз мы находимся под большим контролем.