Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# F受歧视的联合子类型列表_F#_Discriminated Union_Fparsec - Fatal编程技术网

F# F受歧视的联合子类型列表

F# F受歧视的联合子类型列表,f#,discriminated-union,fparsec,F#,Discriminated Union,Fparsec,我想向用户展示一个“FParsec解析器”列表,外加-“测试数据”,用户可以从中交互选择并查看解析器在提供的文本上运行的结果 具体地说,我正试图在这种类型的记录列表中收集我的解析器测试: type FUNCTION_TEST = | XELEMENT_MATCH of label : string * func : Parser<(int * string), unit> * data : string | XKEYVALUE_MATCH of label : st

我想向用户展示一个“FParsec解析器”列表,外加-“测试数据”,用户可以从中交互选择并查看解析器在提供的文本上运行的结果

具体地说,我正试图在这种类型的记录列表中收集我的解析器测试:

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)]

我希望用户查看并选择标签字符串,并查看运行解析器的结果

我知道解析器xElement:parser与解析器xKeyValue:parser不匹配。这两个子类型都是FUNCTION_TEST discriminated union的一部分,但我不能将解析器放在同一个列表中,因为它们的子类型XELEMENT_MATCH与XKEYVALUE_MATCH不一致

我想用火柴来处理这件事。。。与受歧视的工会进行谈判

我不熟悉F和FParsec,也没有什么好主意。我必须用Do硬编码菜单吗!那printfs呢


有经验的F和FParsec开发人员如何允许用户从不同类型的选项菜单中进行选择?

我对函数测试类型有点困惑。看起来您从未使用过该类型或其任何构造函数,如果是这样,那么您为什么要首先定义该类型

在考虑了您可能的动机之后,似乎您希望可测试的_解析器列表包含函数_测试类型的值,以便以后可以匹配它们

如果是这样,那么您所拥有的就不是您想要的:您所构建的列表包含三个值的元组

为了构造FUNCTION_测试类型的值,您需要应用其构造函数:

testableParsers = [
    XELEMENT_MATCH ("xElement", xElement, xElement_text3)
    XKEYVALUE_MATCH ("xKeyValue", xKeyValue, xKeyValue_text)
]
但是,如果您的唯一目的是向用户提供一个选择,那么我甚至不会用一个特殊的类型来表示选项。您可以将标签与用户选择标签时要调用的函数配对:

testableParsers = [
    "xElement", fun() -> runParser xElement xElement_text3
    "xKeyValue", fun() -> runParser xKeyValue xKeyValue_text
]

这样,您也不必对FUNCTION\u TEST的值进行匹配,只需调用该函数。

我认为最好的方法是重新构造数据,以便将所有常见的标签和数据保存在记录中,与表示函数的值一起-该函数可以是一个区分的并集,每种类型有一个大小写:

类型函数= |解析器元素 |解析器的键值 型式试验= {标签:字符串 数据:字符串 函数:函数} 现在,您可以创建一个测试值列表,您可以轻松地对其进行迭代以获取所有标签和数据:

让TestableParser= [{Label=xElement;Function=ElementxElement;Data=xElement\u text3} {Label=xKeyValue;Function=KeyValuexKeyValue;Datta=xKeyValue_text}]
当您想要运行特定函数时,仍然需要使用模式匹配,因为这将需要处理结果中得到的不同值,但您不需要在其他地方进行模式匹配。

谢谢您的回答。我尽量缩短代码片段,希望能节省您的时间。是的,我试着匹配…在功能测试中有区别的联合子类型。因此,我将所有可测试的解析器放在该父类型下,以便它们可以共存于一个列表中。如果F看到类似于XELEMENT_匹配的结构,那么我是否错误地认为F会执行“duck typing”并自动构造XELEMENT_匹配或XKEYVALUE_匹配。当F看到结构化类型的东西时,它不会自动构造该类型吗?谢谢你的回答。为什么F需要显式构造用户定义的类型?F不认识到属于Parser类型的xElement与xElement_MATCH的类型相同,只是自动/隐式地构造正确的用户定义类型吗?当F隐式调用预定义类型(如int和string)的构造函数时,为什么不这样做呢?F能识别与用户定义类型匹配的结构并隐式构造它们吗?我不太确定您的建议-但我想答案是F会引导您以某种方式思考-在这里定义您需要的类型你自己
testableParsers = [
    "xElement", fun() -> runParser xElement xElement_text3
    "xKeyValue", fun() -> runParser xKeyValue xKeyValue_text
]