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=
// ...
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> =
// ...