2012-01-04 3 views
6

Я работаю над разбором CSV-файла в CSV-тип, который является списком Record, который представляет собой список полей, которые являются просто строками. После вставки новой строки, а затем попытки получить доступ к csv, я получаю ошибку переполнения стека c. Я прочитал эту ошибку, может быть, из слишком большого «thunk», используя хвостовую рекурсию, но я не думаю, что то, что я делаю неправильно?«ERROR - C переполнение стека» в Haskell с помощью Hugs

type CSV = [Record] 
type Record = [Field] 
type Field = String 

run :: IO() 
run = 
do 
    inFile <- readFile "myFile.csv" 
    let csv = parse inFile 
    let csv = (insertRow "abc,def,ghi" csv) 
    putStr (show csv) 

insertRow :: String -> CSV -> CSV 
insertRow newRow csv = csv ++ [toRecord newRow] 

parse :: String -> CSV 
parse file = map toRecord (parseLines file "" []) 

toRecord :: String -> Record 
toRecord line = parseWords line "" [] 

-- parseLine input partialCSV records 
parseLines :: String -> String -> [String] -> [String] 
parseLines [] partial records = records ++ [partial] 
parseLines ('\r':xs) partial records = parseLines xs [] (records ++ [partial]) 
parseLines (x:xs) partial records = parseLines xs (partial ++ [x]) records 

-- parseWords input partialRecord fields 
parseWords :: String -> String -> [String] -> [String] 
parseWords [] partial fields = fields ++ [partial] 
parseWords ('"':xs) partial fields = parseQuotes xs partial fields 
parseWords (',':xs) partial fields = parseWords xs [] (fields ++ [partial]) 
parseWords (x:xs) partial fields = parseWords xs (partial ++ [x]) fields 

parseQuotes :: String -> String -> [String] -> [String] 
parseQuotes ('"':xs) partial fields = parseWords xs [] (fields ++ [partial]) 
parseQuotes (x:xs) partial fields = parseQuotes xs (partial ++ [x]) fields 
+5

Не связанный с вашей проблемой, последний выпуск объятий более пяти лет. Язык развивается дальше, также ghci работает лучше (и поставляется с компилятором;). Хотя это печально, я рекомендую больше не использовать объятия (пока кто-то его не оживит). –

ответ

2

Двойной let csv = ... выглядит подозрительно. Не могли бы вы попытаться распутать две переменные? Вероятно, он не делает то, что вы хотите (в Haskell let рекурсивный).

+0

Спасибо за быстрый ответ. Я объединил две кнопки на одной линии, и это сработало! – user1130083

5

Пусть привязок рекурсивны, поэтому эта линия

let csv = (insertRow "abc,def,ghi" csv) 

создает бесконечный цикл, вы определяете csv с точки зрения себя таким образом, что не исчезает. Измените его на

let csv' = ... 

и печать csv' в следующей строке.

+0

Спасибо за быстрый и полезный ответ! Хотя я не совсем уверен в этом. Означает ли это, что я не могу изменить csv, мне нужно продолжать использовать csv ', csv' '...? – user1130083

+2

В Haskell все значения неизменяемы, поэтому вы не можете изменять csv. Поэтому обычно вы должны давать новые имена для значений, которые вы получаете в результате «модификации». Однако вы можете повторно использовать имена _shadowing_ имя, но это работает, только если имя тени/отскока не отображается в RHS его привязки, иначе вхождение в RHS будет ссылаться на новое имя, цикл. У вас может быть 'do {blah; пусть {x = foo; }; пусть {y = bar x; }; пусть {x = baz y; }; quux x; } ', а вторая привязка' x' будет теневой. Но не (в общем) 'let x = foo x', это петли. –

+2

И такое затенение * сильно * обескуражено. Итак ... притворяйтесь, что вы не можете этого сделать, и просто используйте уникальные имена в вложенных путях (где это разумно). –

Смежные вопросы