Как преобразовать тип выбора, автоматически предоставляемый XmlProvider‹›.DomainTypes, в перечисление на F#?

Допустим, у меня есть следующий 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 #:

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

person prokilomer    schedule 01.03.2014    source источник


Ответы (1)


Что ж, чтобы преобразовать строку в 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.Mapping равно None, но это работает с учетом предоставленных здесь данных, потому что e.Mapping всегда имеет значение.

person Mark Seemann    schedule 01.03.2014