"ERROR - C stack overflow" in Haskell using Hugs
Asked Answered
I

2

6

I'm working on parsing a CSV file into a CSV type which is a list of Record which is a list of Field, which are just Strings. After inserting a new row and then trying to access the csv I get the c stack overflow error. I'v read this error may come from too large a "thunk" by using tail recursion but I don't think thats what I'm doing wrong?

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
Inappropriate answered 4/1, 2012 at 14:23 Comment(1)
Unrelated to your problem, hugs' last release is over five years old. The language evolves further, also ghci performs better (and comes with a compiler ;). Although it is sad, I recommend not using hugs anymore (until somebody revives it).Hexone
H
5

let bindings are recursive, so this line

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

creates an infinite loop, you're defining csv in terms of itself in a way that doesn't terminate. Change it to

let csv' = ...

and print csv' in the next line.

Hexone answered 4/1, 2012 at 14:30 Comment(3)
Thanks for the quick and helpful reply! Although I'm not fully sure about the let. Does this mean I cant change csv, I have to keep using csv', csv''...?Inappropriate
In Haskell, all values are immutable, so you can't change csv anyway. So generally you have to give new names to values you obtain as the result of a 'modification'. However, you can reuse names by shadowing the name, but that works only if the shadowed/rebound name doesn't appear on the RHS of its binding, otherwise the occurrence on the RHS would refer to the new name, loop. You can have do { blah; let { x = foo; }; let { y = bar x; }; let { x = baz y; }; quux x; } and the second binding of x would shadow the first. But not (in general) let x = foo x, that loops.Hexone
And such shadowing is highly discouraged. So...pretend like you can't do it, and just use unique names in nested lets (where reasonable).Lacto
B
2

The double let csv = ... looks suspicious. Could you try disentangling the two variables? It probably doesn't do what you want (in Haskell let is recursive).

Badtempered answered 4/1, 2012 at 14:29 Comment(1)
Thanks for the quick reply I combined the two lets onto one line and it worked!Inappropriate

© 2022 - 2024 — McMap. All rights reserved.