Haskell 'scanl with recursion'内存问题

i7uq4tfw  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(107)

我想做以下几件事:

[2,4,3,7,9,3]
[2,6,9,6,5,8]
[2,8,7,3,8,6]
[2,0,7,0,8,4]

字符串
也就是说,在每个阶段中,我想模块化地(在这种情况下为10)将从列表开始到当前位置的所有值相加,创建一个新列表:[2, (2+4)mod10, (2+4+3)mod10, (2+4+3+7)mod10...],我想多次调用它。
我的代码是:

applyMulti :: Int -> [Int] -> [Int]
applyMulti 0 dat = dat
applyMulti n dat = applyMulti (n - 1) $ apply dat

apply :: [Int] -> [Int]
apply dat = scanl1 (\a x -> (a + x) `mod` 10) dat


这对于小数据和小重复计数很好。但是当一个500k Int的列表运行100次时,它会耗尽内存,程序就会被杀死。我不明白为什么即使500k * 100也不应该太大,但编译器甚至可以优化它。
我还尝试了一个非尾递归的版本:

applyMulti n dat = apply . applyMulti (n - 1) $ dat


我甚至使用了:

{-# LANGUAGE BangPatterns, StrictData, Strict #-}


我的错误是什么,我应该如何解决这个问题?

vuktfyat

vuktfyat1#

我不能复制。内存可能会增加200兆字节,其中包括ghci运行时本身。
我们可以使用scanlstrict 版本来提高内存使用率:**scanl' :: (b -> a -> b) -> b -> [a] -> [b]**这将强制计算scanl枚举的列表项:

import Data.List(scanl')

apply :: [Int] -> [Int]
apply [] = []
apply (d:ds) = scanl' (\a x -> (a + x) `mod` 10) d ds

字符串

相关问题