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 printf
s?
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_TEST
type. 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_parsers
list to contain values of theFUNCTION_TEST
type 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_TEST
type, 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
match
on the values ofFUNCTION_TEST
either, just call the function.