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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top