I'm a newbie in F# and in FParsec and have problems with moving my FParsec code into an F# module using VS 2022 Community Edition, DotNet 6.0.
My use case is this: My console app solution currently consists of a single Program.fs that I can build and run without any problems. Now, I want to move some parts of my code to an F# module so I can reuse it. That causes weird type errors I cannot resolve.
This is a working example to reproduce my problem. Consider a console app solution consisting of a single simple Program.fs file containing
open FParsec
let p = pstring "foo"
let result = run p "foo"
printfn "%O" result
I can build and run the code without any problems.
Now, if I create a module MyModule.fs like this:
module MyModule
open FParsec
let p = pstring "foo"
and open it in Program.fs like this:
open FParsec
open MyModule
let result = run p "foo"
printfn "%O" result
I get the following two build errors:
In MyModule.fs, line 3: Error FS0030 Value restriction. The value 'p' has been inferred to have generic type val p: Parser<string,'_a>
Either make the arguments to 'p' explicit or, if you do not intend for it to be generic, add a type annotation.
In Program.fs, line 3: Error FS0001 Type mismatch. Expecting a 'Parser<'a,unit>' but given a 'Parser<string,obj>'
The type 'unit' does not match the type 'obj'
Why do I get these two errors although the code split with the module seems to be semantically identical to the previous code without the module and how can I resolve these errors?
As explained by @Gus in the comments, the problem is that parsers have a second type parameter for user data, that was disambiguated by the call to
runin the original code but not in the modularized code.You can fix this by specifying the full type for the parser:
Then, when you combine several parsers, you'll only need to specify this once and it will disambiguate for all parsers that use it or that it uses. It's typically done on the final parser.