为什么Haskell中的函数product
如果给出一个空列表,则返回1
?
答案 0 :(得分:19)
列表形成 monoid 结构,具有关联二进制操作++
和中性元素[]
。也就是说,我们有
[] ++ xs = xs = xs ++ [] (xs ++ ys) ++ zs = xs ++ (ys ++ zs)
与此同时,数字有很多幺半群结构,但这里的相关结构是操作为*
而中性元素为1
。
1 * x = x = x * 1 (x * y) * z = x * (y * z)
product
函数不仅是从数字到数字列表的映射:它是 monoid同态,反映了数字幺半群中的列表幺半群结构。至关重要的是,
product (xs ++ ys) = product xs * product ys
和
product [] = 1
事实上,为了获得前者,我们几乎将后者强加给我们。
答案 1 :(得分:8)
因为它是乘法类别中的身份。
更实际:
product [1,2,3] == 1 * product 2:3:[]
== 1 * 2 * product 3:[]
== 1 * 2 * 3 * product []
反过来允许您通过简单的递归来实现它:
product [] = 1
product (x:xs) = x * product xs
答案 2 :(得分:7)
这是一个数学问题 - 你通常会将一个空的和定义为0
,将空的产品定义为1
,因为这很符合你通常的法则
例如,通过这种方式,您可以证明产品的归纳定义 - see Wikipedia
答案 3 :(得分:2)
产品是初始值为1的折叠,因此当折叠空列表时,它只返回初始值,即1。
用于说明它的产品实施示例:
product :: [Int] -> Int
product lst = foldr (\x y -> x*y) 1 lst
请查看fold以正确理解。
答案 4 :(得分:0)
我认为这在@Bartek Banachewicz's answer中有最好的解释,但我只想补充一点,那就是所有这些都归结为数学中的一个著名问题;
为什么
0!
等于1
?
Empty
元素不应破坏递归,换句话说,它的行为应类似于identity元素。总之,在数学上,阶乘的递归定义为;
n! = (n+1)! / (n+1)
因此,是Haskell美女
factorial :: Int -> Integer
factorial n = product [1..n]
可以正常工作。我的意思是没有测试n
是否为0
,即[1..0]
产生[]
。这可能是另一个问题主题。