Я написал синтаксический анализатор для большого файла csv, который работает с меньшим подмножеством, но исчерпывает память для строк ~ 1,5 м (фактический файл). После первоначального анализа всех элементов в списке (используя manyTill), я вместо этого использовал состояние парсера для их хранения в одном двоичном дереве поиска - это работало для большого файла.parsec закончился из памяти
С тех пор я разделил «тип элемента» на три отдельных типа и хочу сохранить их в своем собственном дереве, в результате получим три дерева разного типа. Эта версия, однако, работает только для небольшого тестового файла, в то время как у него не хватает памяти для большего.
import qualified Data.Tree.AVL as AVL
import qualified Text.ParserCombinators.Parsec as Parsec
----
data ENW = ENW (AVL.AVL Extent) (AVL.AVL Node) (AVL.AVL Way)
---- used to be Element = Extent | Node | Way in a (Tree Element) - this worked
csvParser :: Parsec String ENW ENW
csvParser = do (Parsec.manyTill (parseL) Parsec.eof) >> Parsec.getState
where parseL = parseLine >> ((Parsec.newline >> return()) <|> Parsec.eof)
parseLine :: Parsec String ENW()
parseLine = parseNode <|> parseWay <|> parseExtents
parseNode :: Parsec String ENW()
parseNode = Parsec.string "node" *> (flip addNode <$> (Node <$> identifier <*> float <*> float)) >>= Parsec.updateState
where identifier = Parsec.tab *> (read <$> Parsec.many1 Parsec.digit)
float = Parsec.tab *> (read <$> parseFloat)
addNode :: ENW -> Node -> ENW
addNode (ENW e n w) node = (ENW e (AVL.push (sndCC node) node n) w)
parseWay и parseExtent следовать той же схеме, и все это начинается с
Parsec.runParser csvParser (ENW AVL.empty AVL.empty AVL.empty) "" input
я не понимаю, как с помощью трех небольших деревьев вместо одной большой один может вызвать проблемы с памятью.
Просто удар в темноте - тип данных Parsec является строгим в параметре «пользовательское состояние», в котором вы храните свои данные. Когда вы непосредственно хранили дерево в этом пользовательском состоянии, оно было строго проверено при разборе. Теперь, когда вы ввели ваши данные в коробку, не имеет значения, что у вас есть три дерева, только если вы поместите дерево в тип данных - деревья будут оцениваться лениво, что может привести к утечкам всякой памяти. Попробуйте сделать ваши поля вашего типа данных строгими. – user2407038