F# 使用不同方案的不同文件中通用Xml的类型?
我有以下代码来处理几个不同的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
节点。现在我发现,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)