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# 使用不同方案的不同文件中通用Xml的类型?_F#_Type Providers_F# Data - Fatal编程技术网

F# 使用不同方案的不同文件中通用Xml的类型?

F# 使用不同方案的不同文件中通用Xml的类型?,f#,type-providers,f#-data,F#,Type Providers,F# Data,我有以下代码来处理几个不同的xml文件(不同的方案),它们都有节点。现在我发现,match部分将在许多地方使用,所以我想为它创建一个函数 let xml1 = XmlProvider<"./file1.xml">.Parse(resp) match xml1.Parameters |> Seq.tryFind (fun x -> x.Name = "token") with | Some value -> value.Value |> Some | No

我有以下代码来处理几个不同的xml文件(不同的方案),它们都有
节点。现在我发现,
match
部分将在许多地方使用,所以我想为它创建一个函数

let xml1 = XmlProvider<"./file1.xml">.Parse(resp) 
match xml1.Parameters |> Seq.tryFind (fun x -> x.Name = "token")  with
| Some value -> value.Value |> Some 
| None -> None

let xml2 = XmlProvider<"./file2.xml">.Parse(resp) // different scheme but has <parameters>
match xml2.Parameters |> Seq.tryFind (fun x -> x.Name = "token")  with
| Some value -> value.Value |> Some 
| None -> None

// more very different files but has <parameters> ......
参数的类型应该是什么

更新: 我已经更新了这个问题。顺便说一句,这是一个显示结构类型有用的例子吗

下面是用于测试的代码(还不可行)
xml1
xml2
具有完全不同的xml方案,只是它们都有
部分

let input1 = """<r1><parameters><parameter name="token">1</parameter><parameter name="other">xxx</parameter></parameters><othersOf1>..sample....</othersOf1></r1>"""
let xml1 = XmlProvider<"""<r1><parameters><parameter name="token">1</parameter><parameter name="other">xxx</parameter></parameters><othersOf1>...</othersOf1></r1>""">.Parse(input1)

let input2 = """<r2><parameters><parameter name="token">1</parameter><parameter name="other">xxx</parameter></parameters><othersOf2>...sample...</othersOf2></r2>"""
let xml2 = XmlProvider<"""<r2><parameters><parameter name="token">1</parameter><parameter name="other">xxx</parameter></parameters><othersOf2>...</othersOf2></r2>""">.Parse(input2)

let getToken (parameters: ????) =
    match parameters |> Seq.tryFind (fun x -> x.Name = "token")  with
    | Some value -> value.Value |> Some 
    | None -> None

let token1 = getToken xml1.Parameters
let token2 = getToken xml2.Parameters
let input1=“”1xxx..sample….”
让xml1=XmlProvider.Parse(input1)
让输入2=“”1xxx…样本…””
让xml2=XmlProvider.Parse(input2)
让getToken(参数:??)=
将参数|>Seq.tryFind(fun x->x.Name=“token”)与
|一些值->值.值|>一些
|无->无
让token1=gettokenxml1.Parameters
让token2=getToken xml2.Parameters

一般来说,嵌套节点的类型成为XML类型提供程序提供的类型的嵌套类型

要访问这些类型,首先需要使用类型别名并命名所提供的类型:

type DbToken = XmlProvider<"""<parameters>
    <parameter name="token" value="123" />
    <parameter name="token" value="123" /> 
  </parameters>""">
下面的调用有效:

let xml = DbToken.GetSample()    
getToken xml.Parameters

其思想是使函数采用某种类型的
^p
seq
,该类型具有
名称
。出于教育目的,
名称
可以是任何类型的
'a
(支持平等),
是通用类型的
'b

let inline get name parameters =
    parameters |> Seq.tryFind (fun x -> (^P : (member Name : 'a) x) = name)
    |> Option.map (fun v -> (^P : (member Value : 'b) v))
将一些值
添加到XML1中,并将名称更改为
int
,以及在XML2
中具有
DateTime
值,可以获得:

let token1 = get "token" xml1.Parameters // : int option
let token2 = get 12 xml2.Parameters // : DateTime option
所以,是的,你是对的,这可以通过利用结构类型来完成

参数的实际类型也取决于
名称。
get
的完整类型为:

name:'a -> parameters:seq< ^P> -> 'b option
  when 'a : equality and  ^P : (member get_Name :  ^P -> 'a) and
        ^P : (member get_Value :  ^P -> 'b)
name:'a->参数:seq<^P>->'b选项
当'a:相等和^P:(成员名:^P->'a)和
^P:(成员获取值:^P->'b)

您是否正在寻找
选项.map
?您需要定义数据类型,然后可以指定它:
类型测试=XmlProvider让xml=Test.Parse(resp)
然后:
让getToken(参数:Test.parameters[])=匹配参数|>Seq.tryFind(fun x->x.Name=“token”)使用| Some value->value.value |>Some | None->None
@FoggyFinder,我已经更新了问题。它比我一开始描述的更复杂。@MarkSeemann我尝试了
xml.Parameters |>Option.ofObj |>Option.map(Seq.tryFind(fun x->x.Name=“token”)
来减少一点代码。但是,它返回的值是
Some(Some…)
,而不是
string option
类型的值。谢谢。我已经更新了这个问题。xml文件有不同的模式,但它们可能都有
节点。如果调用
XmlProvider
两次,您将得到两种不同的类型—对此您无能为力。另一种方法是使用
SampleIsList
parameter()为提供程序指定多个不同的示例-然后共享类型(如果还设置了
Global=true
,则提供程序将基于标记名统一类型)。内联/静态解析类型是否与结构类型功能相同?如何比较?@dc7a9163d9静态解析的类型参数是F#中的结构类型所能得到的,因为F#受标称.NET类型系统的约束。与例如OCaml相比,它的功能不太强大,因为(主要,至少)以下几个方面:-OCaml首先是结构类型的-在F中,您不能声明结构类型或别名,例如
类型P@dc7a9163d9另请参见,(OCaml示例)非常感谢。我测试了代码,但出现了一个错误,所以我发布了另一个问题。你知道为什么会出错吗?应该有
属性。
let token1 = get "token" xml1.Parameters // : int option
let token2 = get 12 xml2.Parameters // : DateTime option
name:'a -> parameters:seq< ^P> -> 'b option
  when 'a : equality and  ^P : (member get_Name :  ^P -> 'a) and
        ^P : (member get_Value :  ^P -> 'b)