我一直在尝试在 Haskell 中学习函数解析,作为练习,我想编写一个简单的元组解析器,使用函数between
和sepBy1
in Text.ParserCombinators.ReadP
. 本质上我想要tupleAsIntPair :: ReadP (Int, Int)
,当使用它解析时ReadP_to_S
需要一个字符串,例如"(3,4)"
并返回(3,4)
装在ReadS
. 目前我有:
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)"
,我得到一个 no parse 错误。另一方面,如果我定义noparens
global 并 run (readP_to_S noparens) "(3,4)"
,我会得到[("3,4","")]
,如果我 run (readP_to_S $ sepBy1 (many1 $ satisfy isNumericOrSep) sep) "3,4"
,我会得到一个 list [(["3"],",4"),(["3,"],"4"),(["3","4"],""),(["3,4"],"")]
,所以至少解析器sepBy1
正在做一些事情,即使我只想要第三次解析。
我认为我正在编写两个解析器between
并且sepBy1
不正确,或者可能sepBy1
没有做我认为应该做的事情。我如何实际实现这个元组解析器?我也将不胜感激任何风格的建议(例如,tuplify2
让我有点烦恼)。