parsing - FParsec 和 pipe3 使参数显式或添加类型表示法
问题描述
我正在尝试使用库中的pipe3
函数,FParsec
但出现错误,我不知道如何解决。
鉴于记录
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"
并返回一个Point
run plistoffloats' "1.1, 3.7"
输入:"1.1, 3.7"
期望的输出:Point = {x = 1.1; y = 3.7;}
错误:
错误 FS0030:值限制。值 'plistoffloats'' 已被推断为具有泛型类型 val plistoffloats' :
Parser <Point,'__a>
要么使 'plistoffloats'' 的参数显式,或者,如果您不打算使其成为泛型,则添加类型注释。
一个更简单的例子pchar
也不起作用。
let parsesA = pchar 'a'
错误 FS0030:值限制。'parsesA' 的值已被推断为具有泛型类型 val parsesA :
Parser<char,'_a>
要么使 'parsesA' 的参数显式,或者,如果您不打算使其成为泛型,则添加类型注释。
解决方案
这在FParsec 文档中有介绍;任何解析器都会发生这种情况。原因是因为在.Net 类型系统中,函数被允许是通用的,但值不是——而在FParsec 中,您通常将解析器定义为值(例如,您通常编写不带参数的let psomething = ...
where )。psomething
阅读链接的文档页面以获得完整的解释——我不会复制和粘贴整个内容——但简短的版本是你可以做以下两件事之一:
创建一个
test
如下所示的函数,并确保它在解析器上的同一源文件中使用: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> = // ...
听起来您正在尝试执行 #1,但除非您的解析器test plistoffloats'
在同一个源文件中被调用,否则 F# 类型推断将无法推断您的用户状态类型并且会给您该错误。
PS您可以在此处阅读有关 F# 值限制错误的更多信息:了解 F# 值限制错误
PPS 的_
第一个位置Parser<_, UserState>
并不意味着“这种类型可以是任何东西”,就像_
在模式匹配等其他上下文中所表示的那样。相反,_
在类型注释中意味着“请为我推断此类型,以便我不必明确指定它”。在 FParsec 上下文中,这非常有用,因为您的所有解析器都将具有UserState
第二个类型参数,但第一个类型参数将具有不同的类型。由于第一个类型参数是类型推断可以推断的,这意味着您可以将类型复制并粘贴Parser<_, UserState>
到所有解析器中,并且 F# 在每种情况下都会做正确的事情。
推荐阅读
- html - 尝试创建锚链接
- assembly - 读/写 vs recvfrom/sendto 系统调用
- xamarin - 使用 DI 从 json 文件中读取 UI Xamarin 测试设置的最佳方法是什么?
- reactjs - 带有反应的 Socket.io 回调
- python - 如何使用python从文本文件中删除选定的文本?
- python - 如何让它显示 y 中 x 轴的值,反之亦然
- r - 为什么以下模除法给出 78 而不是 0?
- php - 高级自定义字段组值为空,但包装元素仍然可见
- python - matplotlib 在 2 台不同的电脑上使用不同的颜色
- android - 有没有办法将 html 5 网页显示到 android/ios 应用程序中?