Это описано в документации FParsec ;это случится с любым парсером.Причина в том, что в системе типов .Net функции могут быть общими, а значения - нет, а в FParsec вы обычно определяете синтаксические анализаторы как значения (например,вы обычно пишете let psomething = ...
, где 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
в качестве аргумента second типа, но будут иметь переменный тип для аргумента типа first .И поскольку аргумент типа first является тем, который может выводить вывод типа, это означает, что вы можете скопировать и вставить тип Parser<_, UserState>
во все ваши синтаксические анализаторы, и F # будет делать правильные вещи ™ в каждом случае.