我想计算一个大文件中每个字符的出现次数。虽然我知道计数应该在Haskell中严格实现(我试图使用foldl实现),但我仍然没有内存。作为比较:文件大小约为2GB,而计算机有100GB内存。该文件中没有太多不同的字符 - 可能是20.我做错了什么?
ins :: [(Char,Int)] -> Char -> [(Char,Int)]
ins [] c = [(c,1)]
ins ((c,i):cs) d
| c == d = (c,i+1):cs
| otherwise = (c,i) : ins cs d
main = do
[file] <- getArgs
txt <- readFile file
print $ foldl' ins [] txt
答案 0 :(得分:7)
您的ins
函数正在创建大量thunks,导致大量memory leak。 foldl'
仅评估为weak head normal form,这还不够。您需要Control.DeepSeq
来自import System.Environment (getArgs)
import Data.Map.Strict (empty, alter)
import qualified Data.ByteString.Lazy.Char8 as B
main :: IO ()
main = getArgs >>= B.readFile . head >>= print . B.foldl' go empty
where
go = flip $ alter inc
inc :: Maybe Int -> Maybe Int
inc Nothing = Just 1
inc (Just i) = Just $ i + 1
才能获得普通表格。
或者,使用deepseq
进行计数,而不是关联列表。此外,如果您的IO大约为2GB,则最好使用Data.Map.Strict
而不是普通字符串。
无论输入大小如何,Bellow代码都应在恒定的内存空间中执行:
{{1}}