product of list iteratively

人走茶凉 提交于 2019-12-02 03:55:19

You can use a fold:

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

This can also be done strictly with foldl' or foldr, the differences mostly are performance, but since you're just starting out I'll skip that lecture this time.


So what does a fold do? Let's start with the basic definition of foldl:

foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f acc [] = acc
foldl f acc (x:xs) = foldl f (f acc x) xs

What this does is takes a function f :: a -> b -> a which takes an accumulator and an additional value, which is fed to it from the list of values. It iteratively applies this function, generating a new accumulator at each step, until it runs out of values in the list. For (*) it looks something like

> 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

I should add that this isn't exactly how it's performed in memory unless you use foldl', which is the strict version, but it's easier to follow this way.

Well in Haskell we don't have loops so iterative is relative, but here's the "functional iteration approach"

 product = foldl' (*) 1

folds are the equivalent of loops in imperative languages. foldl' in particular is tail recursive and strict so it will run in constant space, similar to a loop.

If we were to write it explicitly

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

This is still recursive, but will compile to similar assembly.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!