使用Haskell与Parsec解析|分隔的两个数字列表遇阻求助
Parsec解析问题修复与入门教程推荐
问题修复:数字列表解析错误
你的代码中firstList解析失败的核心原因是空格处理不匹配输入格式:
- 原代码用
many1 (many1 Parsec.digit <* Parsec.space),强制要求每个数字后必须跟空格,但输入中|前的最后一个数字后是空格+|,而你用Parsec.char '|'直接匹配时,没有处理|前的空格,导致解析器在匹配完最后一个数字的空格后,遇到的是空格而非|,触发失败。 - 更合适的做法是用
sepBy1组合子处理数字列表(它专门用于解析分隔符分隔的元素),同时处理|前后的空格。
修正后的代码如下:
import Text.Parsec import Text.Parsec.String (Parser) data Data = Data Int [Int] [Int] deriving Show toInt :: String -> Int toInt = read parseRow :: Parser Data parseRow = do _ <- string "Data" spaces cid <- toInt <$> many1 digit _ <- string ": " firstList <- map toInt <$> sepBy1 (many1 digit) spaces spaces -- 跳过|前的空格 _ <- char '|' spaces -- 跳过|后的空格 secondList <- map toInt <$> sepBy1 (many1 digit) spaces return $ Data cid firstList secondList
关键调整点:
- 用
sepBy1 (many1 digit) spaces替代手动的many1组合,自动处理数字间的任意空格分隔(包括多个空格)。 - 在匹配
|前后显式调用spaces,跳过所有空白字符,兼容输入中|前后的空格变化。 - 可以用
parseTest parseRow "Data 1: 43 76 123 98 32 | 32 88 43 123 43"测试解析效果。
新手友好的Parsec入门资源
- 《Real World Haskell》Parsec章节:这本书的Parsec部分从基础组合子讲起,用实际例子(比如解析配置文件、表达式)逐步讲解,适合新手建立核心概念,重点理解
donotation在解析中的使用,以及string、spaces、sepBy、between等常用组合子的作用。 - Parsec官方文档入门示例:官方文档里的入门部分有简单的解析案例,比如解析CSV、简单表达式,能帮你快速掌握基本用法,同时学会如何调试解析错误(比如用
parseTest查看失败原因)。 - Haskell社区入门教程:很多Haskell博客会有Parsec入门系列,比如从解析简单数字列表开始,逐步扩展到复杂数据结构,重点讲解如何组合小解析器构建大解析器,以及错误处理的基础技巧。
内容的提问来源于stack exchange,提问作者LA.27
相关产品推荐
相关产品推荐

