I want to present the user with a list of 'FParsec parsers'-plus-'test data' from which they can interactively select and see the results of the parser run on the supplied text.
Specifically, am trying to collect my parser tests in a list of records of this type:
type FUNCTION_TEST =
| XELEMENT_MATCH of label : string * func : Parser<(int * string), unit> * data : string
| XKEYVALUE_MATCH of label : string * func : Parser<(string * string), unit> * data : string
let testable_parsers = [( "xElement", xElement, xElement_text3)
( "xKeyValue", xKeyValue, xKeyValue_text)]
xKeyValue above throws the error...
val xKeyValue: Parser<(string * string), unit>
Full name CustomParser.xKeyValue
FS0001:the type '(int * string)' does not match the type 'string * string'
I want the user to see and choose a label string and see the results of running the parser.
I understand that the parser xElement : Parser<int * string, unit> does not match parser xKeyValue : Parser<(string * string), unit>. Both sub-types are part of the FUNCTION_TEST discriminated union BUT I cannot put the parsers in the same list because their sub-types (XELEMENT_MATCH versus XKEYVALUE_MATCH) disagree.
I wanted to handle this using a match ... with over the discriminated union.
I am new to F# and FParsec and out of elegant ideas. Do I have to hard-code a menu with do! and printfs?
How do experienced F# and FParsec developers allow users to select from a menu of options of different types?
I'm a bit confounded by the
FUNCTION_TESTtype. It looks like you're never using the type or any of its constructors, and if so, why did you define that type in the first place?After pondering the possible motives you may have had, it looks like perhaps you wanted the
testable_parserslist to contain values of theFUNCTION_TESTtype so that you can later match on them?If that is the case, then what you have is not what you intended: the list that you have constructed contains tuples of three values.
In order to construct values of the
FUNCTION_TESTtype, you need to apply its constructors:But if your only purpose is to present a choice to the user, then I wouldn't even bother with a special type to represent the options. You can just pair labels with functions to be called when the user chooses the label:
This way you don't have to do a
matchon the values ofFUNCTION_TESTeither, just call the function.