Parsing FParsec和pipe3使参数显式或添加类型表示法

Parsing FParsec和pipe3使参数显式或添加类型表示法,parsing,f#,fparsec,Parsing,F#,Fparsec,我试图使用FParsec库中的pipe3函数,但我遇到了一个不知道如何解决的错误 根据记录 type Point = { x: float; y: float } 和下面的解析器 let plistoffloats' = pipe3 pfloat (pchar ',' .>> spaces) pfloat (fun first z second -> { x = first; y = second }) 我试图实现的是一个解析器,它接收格式为“1.

我试图使用
FParsec
库中的
pipe3
函数,但我遇到了一个不知道如何解决的错误

根据记录

type Point = { x: float; y: float }
和下面的解析器

let plistoffloats' =
    pipe3 pfloat (pchar ',' .>> spaces) pfloat 
        (fun first z second -> { x = first; y = second })
我试图实现的是一个解析器,它接收格式为
“1.1,3.7”
的字符串,并返回一个

run plistoffloats' "1.1, 3.7"
输入
“1.1,3.7”

所需输出
点={x=1.1;y=3.7;}

错误

错误FS0030:值限制。已推断值“plistoflaots”具有泛型类型 val plistoflaots':
解析器
使“parsesA”的参数显式,或者,如果不希望它是泛型的,则添加类型注释

这包括在;任何解析器都会发生这种情况。原因是在.Net类型的系统中,函数允许是泛型的,但值不是泛型的。在FParsec中,您通常将解析器定义为值(例如,您通常编写
let psomething=…
,其中
psomething
不接受任何参数)。阅读链接文档页面了解完整的解释-我不会复制和粘贴整个内容-但简短的版本是,您可以做以下两件事之一:

  • 创建一个如下所示的
    test
    函数,并确保它在解析器的同一源文件中使用:

  • 使用类型注释对解析器进行注释,如下所示:

    type UserState = unit   // You might change this later
    let plistoffloats' : Parser<_, UserState> =
        // ...
    
    type UserState=unit//您可以稍后更改此选项
    设plistoffloats=
    // ...
    
  • 听起来像是在尝试执行#1,但除非在同一源文件中使用
    test plistofloats'
    调用解析器,否则F#类型推断将无法推断用户状态类型,并将给出该错误

    另外,您可以在此处阅读有关F#值限制错误的更多信息:


    p.p.S.
    解析器
    第一个位置的
    并不意味着“这种类型可以是任何东西”,就像
    在模式匹配等其他上下文中所指的那样。相反,类型注释中的表示“请为我推断此类型,这样我就不必显式指定它”。在FParsec上下文中,这非常有用,因为所有解析器都将
    UserState
    作为第二个类型参数,但第一个类型参数的类型不同。由于第一个类型参数是类型推断可以推断的参数,这意味着您可以将类型
    解析器
    复制并粘贴到所有解析器,而F#将做正确的事情™ 在每种情况下。

    感谢您的详细解释和链接。我发现了一个问题,以及为什么在独立运行语句时它在交互中不起作用。如果您使用的是F#interactive窗口,那么解决方案2是最简单的。要在F#Interactive中使用解决方案1,您必须确保在同一突出显示的块中发送解析器和对
    test
    的调用,以便F#Interactive可以有足够的代码来推断用户状态。这可能会让人恼火-我在这里根据个人经验说:-)。解决方案2意味着您可以一次突出显示一个解析器,F#Interactive将推断类型,而不会给出值限制错误。
    let test p str =
        match run p str with
        | Success(result, _, _)   -> printfn "Success: %A" result
        | Failure(errorMsg, _, _) -> printfn "Failure: %s" errorMsg
    
    type UserState = unit   // You might change this later
    let plistoffloats' : Parser<_, UserState> =
        // ...