Haskell中列表的点积

时间:2017-10-09 01:44:53

标签: haskell ghc

我正在尝试仅使用Prelude库中的函数在两个数字列表之间实现点积。我写了以下函数:

dot :: Num a => [a] -> [a] -> a
dot x y = sum $ zipWith (*) x y

我测试如下:

main :: IO ()
main = do
    let n = 10^6
        x = (replicate n 2.0) :: [Double]
        y = (replicate n 3.0) :: [Double]
    print $ dot x y
    return ()

不幸的是,这段代码导致堆栈空间溢出,包含100万个元素的列表(使用ghc 7.6.3和优化标志-O2)。

对于这种简单的情况,我希望ghc能够执行必要的优化以避免递归调用的成本。我错过了什么吗?我的实施错了吗?

1 个答案:

答案 0 :(得分:6)

sum(曾经)用foldr实现。这对于Num大多数实例来说有点愚蠢的选择;严格的左侧折叠更好。使用

import Data.List

sum' :: Num a => [a] -> a
sum' = foldl' (+) 0

而你的堆栈溢出将消失。