我一直在努力学习Haskell中的函数解析,作为练习,我想编写一个简单的元组解析器,使用 Text.ParserCombinators.ReadP
中的函数 between
和 sepBy1
. 基本上我想要 tupleAsIntPair :: ReadP (Int, Int)
,当使用 ReadP_to_S
进行解析时,会使用 "(3,4)"
等字符串并返回 ReadS
中的整数对 (3,4)
. 目前我有:
import Text.ParserCombinators.ReadP
isNumericOrSep :: Char -> Bool
isNumericOrSep = flip elem $ "0123456789-, "
tuplify2 :: [Int] -> (Int, Int)
tuplify2 [x,y] = (x,y)
tupleAsIntPair :: ReadP (Int, Int)
tupleAsIntPair = fmap tuplify2 parsedList
where parsedList = fmap (map read) $ sepBy1 noparens sep
noparens = between open close $ many1 (satisfy isNumericOrSep)
open = char '('
close = char ')'
sep = char ','
但是,当我尝试运行 (readP_to_S tupleAsIntPair) "(3,4)"
时,我得到一个无解析错误 . 另一方面,如果我全局定义 noparens
并运行 (readP_to_S noparens) "(3,4)"
,我得到 [("3,4","")]
并且如果我运行 (readP_to_S $ sepBy1 (many1 $ satisfy isNumericOrSep) sep) "3,4"
,我得到一个列表 [(["3"],",4"),(["3,"],"4"),(["3","4"],""),(["3,4"],"")]
,所以至少解析器 sepBy1
正在做某事,即使我只想要第三次解析 .
我想我正在错误地编写两个解析器 between
和 sepBy1
,或者 sepBy1
没有做我认为应该做的事情 . 我如何实际实现这个元组解析器?我也很感激任何风格的建议(例如, tuplify2
让我有点烦恼) .
1 回答
第一个问题是你对
isNumericOrSep
的定义 . 您定义的列表包含,
作为元素 . 这意味着isNumericOrSep
将解析您用作分隔符的,
,因此parsedList
将失败,因为缺少sep
.那么,你不想定义
isNumeric
吗?为什么在这个定义中需要分隔符?第二个问题是组合器的顺序 . 您的描述在两个
noparens
之间解析sep
,其中noparens
被定义为左括号,多个(但至少一个)数值和右括号的组合 . 所以,我猜你真正想要的是在开括号和右括号之间解析一个元组 .这产生以下结果:
有可能,我误解了你的目标 . 但在你的介绍中,我读到你要解析一个元组 - 但也许你想要解析许多元组?
编辑:
首先不解析括号 . 看看between的定义:
订单再次从左到右 . 首先是
open
,然后解析解析器p
并在结尾close
.