gpt4 book ai didi

Haskell 使用带有 Parsec 的累加器进行解析

转载 作者:行者123 更新时间:2023-12-05 09:36:17 28 4
gpt4 key购买 nike

这里是 Haskell 初学者。

假设我有一个解析器,我提供了一些信息,它返回解析一个部分的结果以及下一部分所需的信息。

readSection :: Info -> Parser (Section, Info)

我希望能够使用 many 组合器解析多个部分,但我无法让这些类型起作用。我需要某种方法让解析器接受先前计算的 Info。这个结构让我想起了一个折叠(因为之前的结果可以只存储在累加器中),但我不确定如何在这里应用它。

readSections :: Info -> Parser [Section]
readSections startInfo = do
let parser = readSection startInfo
-- ???
return $ many readSection

也许有更好的方法来做这样的事情,所以任何指导将不胜感激。谢谢!

最佳答案

如果您正在寻找现有的组合器,这看起来像是来自 monad-loops(以及其他地方)的 unfoldrM 的应用程序。为了避免必须导入它,它可以定义为:

unfoldrM :: Monad m => (a -> m (Maybe (b, a))) -> a -> m [b]
unfoldrM f a = do
r <- f a
case r of
Nothing -> return []
Just (b, a') -> (b:) <$> unfoldrM f a'

基本上,它采用 a 类型的初始种子,并使用它单子(monad)生成值和新种子。您的种子就是您的信息:您使用该信息单子(monad)生成一个已解析的部分以及一个新版本的信息。

您只需加入一个optionMaybe 来提供Just/Nothing 开关,以便unfoldrM 知道什么时候它已到达所有部分的末尾:

readSections = unfoldrM (optionMaybe . readSection)

但是,作为 Haskell 的初学者,了解您如何从头开始做这类事情可能会有所帮助。 many 组合器并不神奇。它基本上等同于相对简单的单子(monad)计算:

many p = (do x <- p
xs <- many p
return (x:xs))
<|> return []

因此,您可以以类似的方式从头开始编写 readSections 作为一元计算:

readSections' :: Info -> Parser [Section]
readSections' i = (do -- try to read a section, getting updated info
(s, i') <- readSection i
-- read zero or more remaining sections with updated info
ss <- readSections' i'
-- return the sections
return (s:ss))
-- if no more sections to read, return an empty list
<|> return []

关于Haskell 使用带有 Parsec 的累加器进行解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65276220/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com