FParsec 无法识别类型的构造函数

FParsec Not Recognizing a Type’s Constructor

以下顶级 XML 解析器定义 return 错误 The value or constructor ‘TOP_LEVEL_RECORD’ is not defined.

let xTop_Level, xTop_Level_Ref = createParserForwardedToRef<TOP_LEVEL_RECORD, unit>()

do xTop_Level_Ref := 
    pipe4 
        (opt xDeclaration) 
        (opt (many xComment_or_CData))
        xElement
        (opt (many xComment_or_CData))
        (fun decl before_root root after_root
            -> {Declaration = decl
                Before_Root = before_root
                Root = root
                After_Root = after_root}) |>> TOP_LEVEL_RECORD
// This returns the error -------------------→^^^^^^^^^^^^^^^^

TOP_LEVEL_RECORD 定义为……

type TOP_LEVEL_RECORD = {Declaration : XDECLARATION option
                         Before_Root : COMMENTS_OR_CDATA list option
                         Root : XELEMENT
                         After_Root : COMMENTS_OR_CDATA list option
                         }

解析器 xDeclarationxCommentor_CdataxElement 均已正确定义,return TOP_LEVEL_RECORD 中的相应类型。

let xTop_Level, xTop_Level_Ref = createParserForwardedToRef<TOP_LEVEL_RECORD, unit>() 是 Fparsec 用于递归解析器调用的语法,记录在此处:http://www.quanttec.com/fparsec/tutorial.html#parsing-json.createParserForwardedToRef-example

如果我定义类型 type TOP_LEVEL = TOP_LEVEL_TYPE of TOP_LEVEL_RECORD 并将 TOP_LEVEL_RECORD 替换为 TOP_LEVELTOP_LEVEL_TYPE 如下…

let xTop_Level, xTop_Level_Ref = createParserForwardedToRef<TOP_LEVEL, unit>()
// Replaced this text ------------------------------------->^^^^^^^^^

do xTop_Level_Ref := 
    pipe4 
        (opt xDeclaration) 
        (opt (many xComment_or_CData))
        xElement
        (opt (many xComment_or_CData))
        (fun decl before_root root after_root
            -> {Declaration = decl
                Before_Root = before_root
                Root = root
                After_Root = after_root}) |>> TOP_LEVEL_TYPE
// Replaced this text ----------------------->^^^^^^^^^^^^^^

...代码编译时没有任何错误或警告。

为什么 TOP_LEVEL_TYPE 这里有一个构造函数而不是 TOP_LEVEL_RECORD

你能指出 F# 或 FParsec 文档的相关部分吗?

TOP_LEVEL_RECORD(记录类型)和TOP_LEVEL(联合类型)是类型名称,不能用作构造函数。

要构造一个 TOP_LEVEL_RECORD,请使用代码中的语法

{ Declaration = decl
  Before_Root = before_root
  Root = root
  After_Root = after_root }

要构造联合类型的实例,您可以使用其中一个案例名称作为构造函数; TOP_LEVEL_TYPE 在你的案例中,因为只有一个联合案例。

请注意,在您的类型定义中

type TOP_LEVEL = TOP_LEVEL_TYPE of TOP_LEVEL_RECORD

TOP_LEVEL 是一种类型,但 TOP_LEVEL_TYPE(尽管它的名称)不是一种类型,而是 TOP_LEVEL 类型的构造函数。

所以记录类型没有命名构造函数,但联合类型有。

对于您的代码,您可以跳过 |>> TOP_LEVEL_RECORD 部分。

您可以在 F# language spec 第 8.4 和 8.5 节中阅读有关记录类型和联合类型的信息。