Haskell中Parsec sepBy函数实现与终端调用问题咨询
嘿,我来帮你捋一捋这个Haskell Parser的问题~你的核心需求是把形如("age",5),("age",6)的字符串转换成带序号的元组列表[("age1",5), ("age2",6)],但原代码确实有几个问题,咱们一步步解决:
先修正Parser的实现
首先,你的代码里存在参数冗余、缺少基础解析逻辑,最重要的是没实现给key加序号的核心功能,咱们重新写:
1. 先实现单个元组的解析器
假设你用的是常用的parsec解析库(如果没装,后面会说怎么装),先写一个能解析("age",5)这种单个元组的解析器:
import Text.Parsec import Text.Parsec.String (Parser) import Data.List (zipWith) -- 解析单个("key", 数字)格式的元组 singleTuple :: Parser (String, Integer) singleTuple = do char '(' -- 匹配开头的( string "\"" -- 匹配左引号 key <- many (noneOf "\"") -- 读取引号内的key(不含引号) string "\"," -- 匹配", numStr <- many1 digit -- 读取数字字符串 char ')' -- 匹配结尾的) return (key, read numStr) -- 把数字字符串转成Integer,返回元组
2. 解析多个元组并添加序号
接下来用sepBy解析逗号分隔的多个元组,然后给每个key拼接递增的序号:
items :: Parser [(String, Integer)] items = do -- 用逗号分隔解析所有单个元组,得到普通元组列表 rawTuples <- sepBy singleTuple (char ',') -- 给每个key加上序号:key1、key2... let numberedTuples = zipWith (\(k, v) idx -> (k ++ show idx, v)) rawTuples [1..] return numberedTuples
这样就完全实现了你的需求:把("age",5),("age",6)解析成[("age1",5), ("age2",6)]。
怎么在终端调用这个解析器?
要运行这个Parser,你需要写一个main函数来接收输入、执行解析并输出结果:
main :: IO () main = do putStrLn "请输入形如(\"age\",5),(\"age\",6)的字符串:" input <- getLine -- 用runParser执行解析,第一个参数是我们的解析器,第二个是状态(这里用()空状态),第三个是输入名称(用于错误提示) case runParser items () "user input" input of Left err -> putStrLn $ "解析出错:" ++ show err Right result -> print result
然后按以下步骤操作:
- 安装parsec库(如果还没装):
- 用cabal的话:
cabal install parsec - 用stack的话:
stack install parsec
- 用cabal的话:
- 把所有代码保存成
TupleParser.hs文件 - 在终端编译运行:
输入测试字符串比如ghc TupleParser.hs ./TupleParser("age",5),("age",6),就能看到预期的输出啦!
原代码的问题总结
- 参数
p被内部的变量绑定覆盖,而且完全没用到,属于冗余参数 - 缺少
strToTup的定义,这会直接导致编译错误 - 没有处理给key添加序号的核心逻辑,这才是你需求的重点
如果需要处理更复杂的输入(比如key带空格、数字是负数),可以再调整解析逻辑哦~
内容的提问来源于stack exchange,提问作者barskyn
相关产品推荐
相关产品推荐

