我想计算大文件中每个字符的出现数量。尽管我知道应该在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
您的ins
功能正在创建大量导致大量内存泄漏的thunk。foldl'
仅评估弱头正常形式,此处还不够。您需要的是Control.DeepSeq
的deepseq
,以便到达正常形式。
另外,使用Data.Map.Strict
代替关联列表进行计数。另外,如果您的IO处于2GB的订单,则最好使用懒惰的ByteString
代替普通字符串。
波纹管代码应在恒定内存空间中执行,而不管输入的大小如何:
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