Haskell中基于柯里化实现双参数变量解析函数的方法
问题解决:用柯里化实现Haskell变量解析
错误原因解析
你遇到的报错核心是:helpersep isSpace返回的是函数类型Parser a -> Parser [a],但do块中<-要求绑定的是一个Parser实例,不是函数。helpersep需要两个参数,你只传了第一个,所以得到的是等待第二个参数的柯里化函数,无法直接作为解析器使用。
柯里化的正确用法
你的目标是固定分隔符为空格,让辅助函数只接收待解析的p参数。首先调整辅助函数的定义,利用柯里化特性让它先接收分隔符,返回一个等待解析器参数的函数:
-- 等价于 flip sepBy,固定分隔符sep,返回接收解析器p的函数 helpersep :: Parser a -> Parser a -> Parser [a] helpersep sep p = sepBy p sep
或者更简洁地写成柯里化的点-free形式:
helpersep :: Parser a -> Parser a -> Parser [a] helpersep = flip sepBy
现在,helpersep space会返回Parser a -> Parser [a],接下来你需要传入匹配非空格字符的解析器作为第二个参数,才能得到真正可执行的Parser [a]。
完整的变量解析实现
变量解析需要满足:首字符不能是数字,后续可以是任意非空格字符。结合柯里化的正确用法,完整代码如下:
import Text.ParserCombinators.ReadP import Data.Char (isSpace, isDigit, isAlphaNum) -- 匹配单个空格 space :: Parser Char space = satisfy isSpace -- 固定分隔符的柯里化辅助函数 helpersep :: Parser a -> Parser a -> Parser [a] helpersep = flip sepBy -- 解析变量:首字符为字母/下划线,后续为字母数字/下划线,直到空格结束 pIdent :: Parser String pIdent = do -- 解析首字符:不能是数字或空格 first <- satisfy (\c -> not (isSpace c || isDigit c)) -- 用柯里化的helpersep,固定分隔符为space,传入匹配非空格字符的解析器 rest <- helpersep space (many (satisfy (\c -> not (isSpace c)))) -- 拼接首字符和后续字符 return (first : concat rest)
测试验证
执行readP_to_S pIdent "someVar = 4",会得到结果[("someVar", " = 4")],符合解析变量到空格的预期。
额外说明
你之前代码中的get是获取当前解析位置的状态,不是读取字符,应该用satisfy来读取并匹配字符。另外,变量名通常允许下划线,解析首字符时可以根据需求调整判断逻辑(比如加入c == '_'的条件)。
内容的提问来源于stack exchange,提问作者Piskator
相关产品推荐
相关产品推荐

