声明式语言的哪些具体优势使其比命令式语言更适用于人工智能?
声明性语言可以轻松完成哪些其他语言风格难以解决此类问题的事情?
声明式语言的哪些具体优势使其比命令式语言更适用于人工智能?
声明性语言可以轻松完成哪些其他语言风格难以解决此类问题的事情?
像 Prolog 这样的声明性语言的优点是它可以用来表达与控制流分开的事实和推理规则。
这允许开发者专注于数据和推理规则(知识模型),并允许开发者更容易地扩展知识模型。
我应该补充一点,在实践中,事实/规则和控制流之间的这种二分法并不严格。使用 Prolog 编写代码库的知识工程师有时必须考虑控制流。这 ”!” 使用运算符,以便开发人员可以影响规则的评估。
没有客观的理由说声明性语言更适合 AI 开发。然而,在实践中确实存在对它们的偏见。尽管大多数函数式语言是不纯的(即它们允许副作用),并且不能算作“声明性”,但少数语言是纯粹的函数式(即它们不允许副作用),最突出的是Haskell。纯度是这里的关键。在 Haskell 中,甚至 I/O 也是 pure。
命令式语言和(纯)函数式语言之间的主要区别在于它们描述程序的方式。命令式程序描述了如何做事,即算法。它指定了机器为了执行计算而必须执行的特定指令。OTOH,纯函数式语言描述要计算的内容,即输入和输出之间的关系。在数学中,“函数”只是输入和输出之间关系的一个花哨的名称。
同样,在数学意义上,唯一的可变性是函数参数的可变性。也就是说,函数的输出完全取决于它的输入(参数)。这称为参照透明性。参考透明度指出:
在哪里是所有函数的集合,并且是的域。对于典型的命令式语言对“函数”的定义,上述不成立。例如,Cgetchar()
并不总是返回相同的值。
假设我们要计算最低有效位为的十个最小素数的集合. 首先,在数学符号中:
G(n, s)
中的较小n
元素的集合在哪里s
。在数学中,您不必担心集合如何应该是计算的,而是关于的定义本身。
现在,在 Python 中(命令式):
def is_prime(n):
for x in range(2, n):
if n % x == 0:
return False
return True
def foo():
s = set()
n = 2
while len(s) < 10:
if is_prime(n) and n % 10 == 3:
s.append(n)
return set(s)
在 Python 中,我们关心(并负责)用于计算集合的算法。我们几乎以配方风格指定如何从头开始构建集合。如果有一种算法可能更适合检查一个数字是素数还是奇数,但我们不使用它,这是我们的错,而不是 Python 的错。
最后,Haskell 介入:
import qualified Data.Set as Set
isPrime :: Integer -> Bool
isPrime n = ( == 1 ) . length . filter ( == 0 ) . map ( n `mod` ) $ [ 2 .. n ]
s = Set.fromList . take 10 . filter ( ( == 3 ) . ( `mod` 10 ) ) . filter isPrime $ [1..]
Haskell 的版本比 Python 更像数学模型。我们isPrime
根据素数必须遵守的约束来定义函数,而不是通过描述逐步算法来进行这种检查。此外,s
(到目前为止我们一直在定义的集合)是根据其成员必须遵守的约束来定义的,而不是根据计算s
自身的算法来定义的。编译器,通常不是The Glorious Glasgow Haskell Compilation System (aka GHC),负责生成算法。GHC 的优化器被认为是世界上最强大的优化器之一,不是因为它是所有编译器中最好的,而是因为 Haskell 的特性允许这样做。
总而言之,Haskell(和其他函数式语言)有几个特性使它看起来、尝起来和表现得像纯数学:
参考透明度和纯度。
一个非常强大的类型系统,具有诸如递归(和代数)数据类型之类的奇特(但非常有用!)的东西。
因此,底线是人工智能研究人员通常更喜欢函数式语言而不是命令式语言(或者,更自信的是,纯粹而不是不纯的语言),因为他们试图通过函数(输入和输出之间的关系)来定义人工智能本身)。最后,我们这样做是因为我们没有真正的算法可以从少数晶体管中获得人类级别的智能。此外,从Lisp 的创造者和早期 AI 研究的先驱John McCarthy开始,对这类语言存在历史偏见。