函数式编程是声明式编程的一种类型吗?

11

我知道声明式编程只是传递输入并期望输出,而不陈述它是如何完成的过程。在函数式编程中,这是一种编程范式,它接受输入并返回输出。当我检查高阶函数式编程时,我们将函数传递给map/reduce,但没有揭示它是如何完成的过程。那么高阶函数式编程和声明式编程是否相同?


5
函数式编程和声明式编程并不完全相同,反之亦然。Prolog是一种逻辑编程语言,被许多人认为也是一种声明式编程语言。但我认为这些术语有点模糊。 - Willem Van Onsem
2
请参考此前的SO问题以获取相关答案:函数式、声明式和命令式编程 - tex
2个回答

11

简短回答: 不是

维基百科声明式编程定义为:

在计算机科学中,声明式编程是一种编程范例——一种构建计算机程序结构和元素的方式,它表达了计算逻辑而不描述其控制流程

或者更大胆地说:“说出你想要的,而不是你想要的方法。”。

这与命令式编程语言形成对比,在其中,程序被看作是一系列指令依次执行。虽然map等函数“不显示过程”,但这并不意味着它具备声明式:你可以使用许多C库,这些库是专有的,不允许您检查源代码。然而,这并不意味着它们是声明性的。

另一方面,函数式编程的定义是:

在计算机科学中,函数式编程是一种编程范式——一种构建计算机程序结构和元素的方式,它将计算视为数学函数的评估,并避免了更改状态和可变数据。它是一种声明式编程范式,这意味着使用表达式或声明进行编程,而不是语句。

基于这些定义,可以说函数式编程是声明式编程的一个子集。然而,在实际应用中,如果我们遵循严格的定义,现在没有一种编程语言是纯粹、明确的声明式编程函数式编程。然而,可以说Haskell比Java更加声明性

通常认为声明式编程更“安全”,因为人们往往难以管理副作用。许多编程错误是由于未考虑所有副作用而产生的。另一方面,做到以下几点很难:

  1. 设计一种语言,使程序员能够描述他想要什么,而不必详细说明如何做到这一点;
  2. 实现一个编译器,它将基于这样的程序生成一个高效的实现;以及
  3. 一些问题具有固有的副作用。例如,如果您使用数据库、网络连接或文件系统,则读取/写入文件通常会具有副作用。当然,可以决定不将其作为编程语言的一部分(例如,许多约束编程语言不允许这些类型的操作,并且是一个更大系统中的“子语言”)。

已经有几个尝试设计这种语言的方法。最流行的是——在我看来——逻辑编程函数式编程约束编程。每种方法都有其优点和问题。我们还可以在数据库(如SQL)和文本/XML处理中观察到这种声明性方法(使用XSLTis_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 应该如何评估它。尽管惰性编程会导致程序员并不真正指定应该先评估什么,但仍然有规范说明 Haskell 如何评估这个问题。

据一些人称,这是“编程”和“规定”的区别。我的一位教授曾经说过,他认为区别在于当你编写程序时,你在某种程度上会控制评估方式,而当你“规定”某些东西时,你没有任何控制。但是,这只是许多定义中的一个


3
并非完全如此,函数式编程更加强调计算什么而不是如何计算。然而,在函数式编程中有一些模式与声明式编程中常见的控制流模式非常相似,例如以下控制流模式:
let continue = ref true in
while !continue do
  ...
  if cond then continue := false
  else
     ...
done

看起来很熟悉,对吧?在这里,您可以看到一些声明性结构,但这次我们有更多的控制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接