【发布时间】:2014-03-03 10:06:45
【问题描述】:
我有一个场景,我使用 FSharp.Data 中的 XML 类型提供程序来读取包含各种键/值对的流。这种情况下的值有时是小数,有时是日期,有时是字符串:
<records>
<fields>
<key>foo</key>
<value>123.456</value>
</fields>
<fields>
<key>bar</key>
<value>2013-07-23</value>
</fields>
<fields>
<key>fizz</key>
<value>hello world</value>
</fields>
</records>
因为似乎没有办法按名称引用提供的类型,为了对值进行模式匹配,我必须将值移动到元组中,然后在其上提供活动模式:
open System
open System.IO
type XmlFoo=FSharp.Data.XmlProvider<"""<records>
<fields>
<key>foo</key>
<value>123.456</value>
</fields>
<fields>
<key>bar</key>
<value>2013-07-23</value>
</fields>
<fields>
<key>fizz</key>
<value>hello world</value>
</fields>
</records>""">
[<EntryPoint>]
let main argv =
let (|Date|_|) ((v,_,_):Option<DateTime> * Option<Decimal> * Option<String>) = v
let (|Number|_|) ((_,v,_):Option<DateTime> * Option<Decimal> * Option<String>) = v
let (|String|_|) ((_,_,v):Option<DateTime> * Option<Decimal> * Option<String>) = v
use stream = File.OpenRead("sample.xml")
let data = XmlFoo.Load(stream)
for field in data.Fields do
let value = field.Value.DateTimeValue, field.Value.NumberValue, field.Value.StringValue
match value with
| Date x -> printfn "Found a date: %s" (x.ToShortDateString())
| Number x -> printfn "Found a number: %M" x
| String x -> printfn "Found a string: %s" x
| _ -> printfn "Found nothing"
0 // return an integer exit code
有没有办法 a) 直接引用提供的类型(所以我不需要中间元组,并且活动模式可以推广到返回任意数量的可能数据类型的 XML 文件) 或者 b) 修改类型提供程序,以便它自己提供活动模式 - 不确定这是否可能查看类型提供程序 API。
编辑:没关系,我错过了明显的 - VS2013 中的工具提示具有误导性。通过显示 <...> 它给人的印象是没有办法通过名称来引用类型。感谢@ovatsus 的提示。你可以这样做:
open System
open System.IO
type XmlFoo=FSharp.Data.XmlProvider<"""<records>
<fields>
<key>foo</key>
<value>123.456</value>
</fields>
<fields>
<key>bar</key>
<value>2013-07-23</value>
</fields>
<fields>
<key>fizz</key>
<value>hello world</value>
</fields>
</records>""">
[<EntryPoint>]
let main argv =
let (|Date|_|) (v:XmlFoo.Value) = v.DateTimeValue
let (|Number|_|) (v:XmlFoo.Value) = v.NumberValue
let (|String|_|) (v:XmlFoo.Value) = v.StringValue
use stream = File.OpenRead("sample.xml")
let data = XmlFoo.Load(stream)
for field in data.Fields do
match field.Value with
| Date x -> printfn "Found a date: %s" (x.ToShortDateString())
| Number x -> printfn "Found a number: %M" x
| String x -> printfn "Found a string: %s" x
| _ -> printfn "Found nothing"
0 // return an integer exit code
【问题讨论】:
标签: f# type-providers