我是Haskell的新手,所以我既天真又好奇。
有一个阶乘函数的定义:
factorial n = product [1..n]
我天真地将其理解为:使每个数字的乘积在1和n之间。那么,为什么呢
factorial 0
返回1(就我的数学不太生锈而言,这是一个好结果)?
谢谢
答案 0 :(得分:13)
这是因为如何定义 product
,如:
product [] = 1
product (n:ns) = n * product ns
或等效
product = foldr (*) 1
通过重要功能foldr
:
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
阅读折叠here。但基本上,任何递归都必须有一个基本情况,而product
的基本情况(在空列表中)显然必须为1.
答案 1 :(得分:5)
关于 空产品 的故事很长很有趣。
现在我举一个例子,当空产品约定产生令人惊讶的,不直观的结果时。
如何定义 prime 的概念,而无需明确排除1?看起来很不美观,可以说“除了这个和那个”之外,“鼎盛时期就是如此。”可以用一些方便的定义来定义素数的概念,这种定义可以以“自然”,“自动”的方式排除1,而不明确地提及排除吗?
让我们尝试这种方法:
让我们调用一个自然数 c 复合,iff c 可以写成某些 a 1的产品,...,⋅ a n 自然数,因此所有这些都必须与 c 不同。
让我们调用一个自然数 p prime,iff p 不能写成任何 a 1的产品, a n 自然数,每个都与 p 不同。
让我们测试这种方法是否有用:
6 = 6⋅1
3⋅2
6是复合的,这个事实通过以下因子分解:6可以写为产品3⋅2,或者换句话说,⟨3,2⟩序列的乘积,标记为Π⟨3,2⟩。
直到现在,我们的新方法是O.K。
5 = 5⋅1
1⋅5
5是素数,没有序列⟨ a 1 ,... a n ⟩,以便
到目前为止,我们的新方法是O.K。
现在让我们调查1:
1 =Π⟨⟩,
空产品是一个很好的见证,凭借它,1 满足 复合 的定义( !!!)谁是证人?目击因素化在哪里?它只不过是空产品Π⟨⟩,是空序列的产物<。
因此,根据定义,1被排除为素数,自然和自动。我们已达到目标。为此,我们利用了关于空产品为1的惯例。
一些缺点:虽然我们成功地将1排除为素数,但同时,0“滑入”:0成为素数(至少在零除数自由环中,如自然数)。虽然这个奇怪的东西使得一些定理在形式上更简洁(Goldbach猜想,算术的基本定理),但我不能代表它不是一个缺点。
更大的缺点是,使用这种新方法,某些算术概念似乎变得难以维持。
在任何情况下,我只想证明将空产品定义为1可以产生形式化不直观的事物(这不一定是问题,集合理论充满了不直观的事情,参见how to produce gold for free),但是在同时,它可以在某些情况下提供有用的力量。
答案 2 :(得分:4)
传统的做法是将空列表的所有元素的乘积定义为1,就像传统的将空列表的所有元素的总和定义为0.那样
(product list1) * (product list2) == product (list1 ++ list2)
其他方便的属性。
另外,你的记忆是正确的,0!被定义为1.这也有许多方便的属性,包括与gamma function方面的阶乘定义一致。
答案 3 :(得分:-2)
不确定我理解你的问题,你在问这个函数怎么写?
就像练习一样,你可以使用模式匹配来接近它:
factorial :: Int->Int
factorial 0 = 1
factorial n = product [1..n]
第一行是函数声明/类型签名。后两行是定义函数的等式 - Haskell模式匹配将实际运行时参数与适当的等式相匹配。
当然,正如其他人所指出的那样,产品功能正确地为您处理零件。