我正在用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
,目前尚未实现。)
答案 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)