如何将XmlProvider< ...> .DomainTypes自动提供的选择类型转换为F#中的枚举?

时间:2014-03-01 12:56:44

标签: xml f# enumeration type-providers f#-data

假设我有以下XML:

<?xml version="1.0" encoding="UTF-16"?>
<iAmConfused>
    <helpMe feeling="anger" strength="100" mapping="1-1" />
    <helpMe feeling="frustration" strength="15" mapping="1-n" />
    <helpMe feeling="helplessness" strength="365" mapping="1-1" />
    <helpMe feeling="despair" strength="-1" mapping="1-n" />
</iAmConfused>

并希望将其转换为F#Map:

open System.Xml
open System.Xml.Linq
open FSharp.Data

type mappingType =
    | oneToOneMapping = 00
    | oneToManyMapping = 01

type helpMe = {
    strength : int;
    mapping : mappingType}

type iAmConfusedXmlType = XmlProvider<"""<?xml version="1.0" encoding="UTF-16"?><iAmConfused><helpMe feeling="anger" strength="100" mapping="1-1" /><helpMe feeling="frustration" strength="15" mapping="1-n" /><helpMe feeling="helplessness" strength="365" mapping="1-1" /><helpMe feeling="despair" strength="-1" mapping="1-n" /></iAmConfused>""">

let iAmConfusedXml = iAmConfusedXmlType.Parse("""<?xml version="1.0" encoding="UTF-16"?><iAmConfused><helpMe feeling="anger" strength="100" mapping="1-1" /><helpMe feeling="frustration" strength="15" mapping="1-n" /><helpMe feeling="helplessness" strength="365" mapping="1-1" /><helpMe feeling="despair" strength="-1" mapping="1-n" /></iAmConfused>""")

let iWantThisMap =
    iAmConfusedXml.GetHelpMes()
    |> Seq.map (fun e -> e.Feeling, {
        strength = e.Strength;
        mapping = ???})
    |> Map.ofSeq

XmlProvider正确地将XML属性mapping的类型推断为XmlProvider<...>.DomainTypes.MappingChoice。但是,我找不到将此类型转换为mappingType的方法。

首先,我尝试将XML属性mapping转换为字符串,然后希望将其转换为枚举mappingType,但即使这对我来说太难了......

在上面的代码中重写类型helpMe:

type helpMe = {
    strength : int;
    mapping : string}

然后将???替换为

string e.Strength

给我"Some(1-1)""Some(1-n)" helpMe.mapping这不是我想要的。
如果我尝试将???替换为

string (defaultArg e.Mapping "")

然后FSI理所当然地抱怨道:

test.fs(165,38): error FS0001: This expression was expected to have type
    'a option    
but here has type
    XmlProvider<...>.DomainTypes.MappingChoice

1 个答案:

答案 0 :(得分:2)

好吧,要从字符串转换为mappingType,您可以定义一个小帮助函数:

let convert m =
    match m with
    | "1-1" -> mappingType.oneToOneMapping
    | _ -> mappingType.oneToManyMapping

这使您可以编写投影,如:

let iWantThisMap =
    iAmConfusedXml.GetHelpMes()
    |> Seq.map (fun e -> e.Feeling, {
        strength = e.Strength;
        mapping = (e.Mapping.Value |> convert) })
    |> Map.ofSeq

现在,这里有一些作弊,因为它只是调用e.Mapping.Value。如果e.MappingNone,则可能会引发异常,但是根据此处提供的数据,它会起作用,因为e.Mapping总是有值。