使用Hugs在Haskell中使用"ERROR - C stack overflow"

use*_*083 6 stack-overflow haskell hugs

我正在努力将CSV文件解析为CSV类型,这是一个Record列表,它是Field的列表,它只是字符串.插入新行然后尝试访问csv后,我得到c堆栈溢出错误.我读过这个错误可能来自太大的"thunk"使用尾递归,但我不认为那是我做错了什么?

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
Run Code Online (Sandbox Code Playgroud)

Dan*_*her 5

让绑定是递归的,所以这一行

let csv = (insertRow "abc,def,ghi" csv)
Run Code Online (Sandbox Code Playgroud)

创建一个无限循环,你csv以一种不终止的方式定义自己.将其更改为

let csv' = ...
Run Code Online (Sandbox Code Playgroud)

csv'在下一行打印.

  • 在Haskell中,所有值都是不可变的,因此无论如何都无法更改csv.因此,通常您必须为由于"修改"而获得的值赋予新名称.但是,您可以通过_shadowing_名称重用名称,但仅当阴影/回弹名称未出现在其绑定的RHS上时才有效,否则RHS上的出现将引用新名称loop.你可以做'做{blah; 让{x = foo; }; 让{y = bar x; }; 让{x = baz y; }; quux x; ``和`x`的第二个绑定会影响第一个.但是(通常)`let x = foo x`,循环. (2认同)
  • 并且这种阴影被高度劝阻.所以...假装你不能这样做,只在嵌套的let中使用唯一的名称(在合理的情况下). (2认同)

Shi*_*iSi 2

双倍let csv = ...看起来很可疑。你能尝试解开这两个变量吗?它可能不会做你想要的(在 Haskell 中let是递归的)。