【发布时间】:2021-09-11 03:50:24
【问题描述】:
我正在用 Haskell 为一种简单的语言创建一个解析器。解析器获取由单独的标记器生成的标记列表,并将其转换为结构化树。在编写此 Parser 时,我遇到了一个我想概括的重复出现的模式。以下是相关定义:
--Parser Definition
data Parser a b = Parser { runParser :: [a] -> Maybe ([a], b) }
--Token Definition
data Token = TokOp { getTokOp :: Operator }
| TokInt { getTokInt :: Int }
| TokIdent { getTokIdent :: String }
| TokAssign
| TokLParen
| TokRParen
deriving (Eq, Show)
解析器还为 MonadPlus 及其所有超类定义了实例。以下是我试图概括的重复出现模式的两个示例:
-- Identifier Parser
identP :: Parser Token String
identP = Parser $ \input -> case input of
TokIdent s : rest -> Just (rest, s)
_ -> Nothing
--Integer Parser
intP :: Parser Token Int
intP = Parser $ \input -> case input of
TokInt n : rest -> Just (rest, n)
_ -> Nothing
如您所见,这两个示例非常相似,但我认为无法一概而论。理想情况下,我想要一些 extractToken :: ?? -> Parser Token a 类型的函数,其中 a 是令牌包含的值。我猜该解决方案涉及>>=,但我对 Monads 的经验不足,无法弄清楚。这也可能是不可能的,我不确定。
【问题讨论】:
-
如果我建议像
(a -> Maybe b) -> Parser a b这样的类型,是否足以弄清楚该怎么做? -
是的,这是有道理的。您正在描述以下答案(由 K. A. Buhr 撰写的答案)所说的更通用的版本,对吗?
-
是的,我就是这么想的。
标签: parsing haskell functional-programming token monads