Haskell中的递归解析器

时间:2019-12-23 09:49:56

标签: haskell parsec

我正在用Haskell编写一个解析器,解析函数之一(prefixParser)应该在每次调用时返回其自身的修改版本。这里的代码已简化,但我希望包括所有必要的信息。

type MyParsec r = Parsec [Char] () Identity r

newtype SomeResult = String

newtype RecursiveParser = MyParsec (SomeResult, RecursiveParser)

items :: RecursiveParser -> MyParsec [SomeResult]
items prefixParser = do
  (someResult, newPrefixParser) <- prefixParser
  rst <- items newPrefixParser
  return (someResult : rst)

现在麻烦的是,prefixParser的类型为RecursiveParser,但是我在需要do的{​​{1}}块中调用它。嗯,我得到了

  

无法匹配预期的类型

错误。我什至可以做这样的事情吗?还是我(像往常一样)不太了解Haskell的类型系统?

MyParsec旨在解析递增的数字prefixParser,目前尚未实现。)

1 个答案:

答案 0 :(得分:2)

这是错误的:

newtype RecursiveParser = MyParsec (SomeResult, RecursiveParser)

上面,MyParsec是新数据构造函数的名称,它与MyParser类型的构造函数完全无关。本质上,以上定义将RecursiveParser定义为一对(SomeResult, RecursiveParser),并包装在新的构造函数MyParsec下。

回想newtype的语法是

newtype NewtypeName = NewConstructorName SomeType

要实际使用MyParsec (...)类型,您需要如下指定构造函数的名称。通常使用与newtype本身相同的名称来命名它。

newtype RecursiveParser = RecursiveParser (MyParsec (SomeResult, RecursiveParser))

然后,您可以修改代码,以删除包装器数据构造函数。

items :: RecursiveParser -> MyParsec [SomeResult]
items (RecursiveParser prefixParser) = do
  (someResult, newPrefixParser) <- prefixParser
  rst <- items newPrefixParser
  return (someResult : rst)