我正在尝试在Haskell中学习编码。
我从一个简单的例子“列表的产品”开始。
product :: [Integer] -> Integer
product [] = 1
product (x:xs) = x * product xs
我很快完成了这个。 另一种方式是API中的产品功能。 (产品清单 - >产品)
我想知道是否有另一种迭代方式来解决我的问题?
答案 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
这仍然是递归的,但会编译成类似的程序集。