迭代的列表产品

时间:2014-01-21 22:22:47

标签: list haskell product

我正在尝试在Haskell中学习编码。

我从一个简单的例子“列表的产品”开始。

product :: [Integer] -> Integer  
product []     = 1  
product (x:xs) = x * product xs

我很快完成了这个。 另一种方式是API中的产品功能。 (产品清单 - >产品)

我想知道是否有另一种迭代方式来解决我的问题?

2 个答案:

答案 0 :(得分:3)

您可以使用折叠:

product :: Num a => [a] -> a
product xs = foldl (*) 1 xs

这也可以通过foldl'foldr严格执行,差异主要是表现,但由于您刚刚开始,我这次会跳过这个讲座。


折叠是做什么的?让我们从foldl

的基本定义开始
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f acc [] = acc
foldl f acc (x:xs) = foldl f (f acc x) xs

这样做需要一个函数f :: a -> b -> a,它带有一个累加器和一个附加值,它从值列表中输入。它迭代地应用此函数,在每一步生成一个新的累加器,直到它用完列表中的值。对于(*),它看起来像

> foldl (*) 1 [1, 2, 3, 4]
|   foldl (*) (1 * 1) [2, 3, 4] = foldl (*) 1 [2, 3, 4]
|   foldl (*) (1 * 2) [3, 4]    = foldl (*) 2 [3, 4]
|   foldl (*) (2 * 3) [4]       = foldl (*) 6 [4]
|   foldl (*) (6 * 4) []        = foldl (*) 24 []
|   24

我应该补充一点,除非你使用foldl'这是严格的版本,否则这并不是它在内存中的执行方式,但更容易遵循这种方式。

答案 1 :(得分:1)

在Haskell中我们没有循环所以迭代是相对的,但这里是“功能迭代方法”

 product = foldl' (*) 1

折叠相当于命令式语言中的循环。 foldl'特别是尾递归和严格,因此它将在恒定空间中运行,类似于循环。

如果我们要明确地写它

 product = go 1
   where go accum (x:xs) = go (accum * x) xs
         go accum _      = accum -- Subtle performances
                                 -- differences with strictness

这仍然是递归的,但会编译成类似的程序集。