I want to use the FParsec createParserForwardedToRef function with a generic Expr union, like this:
type Expr<'Term> =
| Unary of Operator * Expr<'Term>
| Binary of Operator * Expr<'Term> * Expr<'Term>
| Ternary of Operator * Expr<'Term> * Expr<'Term> * Expr<'Term>
| Term of 'Term
let expr, exprR = createParserForwardedToRef<Expr<'T>,unit>()
I can't get rid of the value restriction error. I can't turn expr
into a CLR function, much less exprR
.
How would I normally deal with this situation?
The tricky bit is the generic Expr<'T>
. You can make a function that returns expr
parser, and let subsequent use of parsers determine a specific type of Expr<'T>
:
let expr() =
// initially exprRef holds a reference to a dummy parser
let expr, exprRef = createParserForwardedToRef()
// create other union-case parsers as inner or outer functions
let unary() = ...
let binary = ...
let ternary() = ...
let term() = ...
// replace dummy parser reference in exprRef
do exprRef := choice [unary(); binary(); ternary(); term()]
expr
You could also pass primitive parsers such as term
as arguments to expr
function. In this case, type of expr
depends on different kinds of parsers passed on e.g. pstring
, pfloat
.
FParsec tutorial has a section on F# value restriction which might also be helpful.