假设我想解析语言X的文件。真的,我只对其中的一小部分信息感兴趣。为此目的,在 Haskell 的众多 eDSL 之一中编写解析器很容易(例如 Megaparsec)。
data Foo = Foo Int -- the information I'm after.
parseFoo :: Parsec Text Foo
parseFoo = ...
这很容易产生一个函数getFoo :: Text -> Maybe Foo
。
但是现在我也想修改信息的来源Foo
,即基本上我要实现
changeFoo :: (Foo -> Foo) -> Text -> Text
与属性
changeFoo id ≡ id
getFoo . changeFoo f ≡ fmap f . getFoo
可以通过将解析器的结果更改为类似镜头的东西来做到这一点
parseFoo :: Parsec Text (Foo, Foo -> Text)
parseFoo = ...
但这使得定义变得更加麻烦——我不能再掩盖不相关的信息,而是需要存储每个子解析的匹配string
并手动重新组合它。
这可以通过将字符串重新组合保持在StateT
解析器 monad 周围的层中来实现某种程度的自动化,但我不能只使用现有的原始解析器。
这个问题有现成的解决方案吗?