F# и явное преобразование в LINQ to XML

В С# я могу выразить это:

var xe = XElement.Parse("<foo></foo>");
var maybe = (bool?)xe.Element("bar");

Как это можно выразить в F#?

Изменить: я нашел эту вспомогательную функцию

let inline conv (x : ^a) : ^b = ((^a or ^b) : (static member op_Explicit : ^a -> ^b) (x))

person Bent Rasmussen    schedule 13.11.2013    source источник
comment
Варианты см. здесь: trelford.com/blog/post/   -  person N_A    schedule 14.11.2013


Ответы (1)


К сожалению, XLinq сильно зависит от неявных и явных преобразований, что немного усложняет задачу.

Вы можете создать подпрограмму для преобразования из XElement в логическую опцию:

let elementToBool e =
  match e with
    | null -> None
    | e -> Some(XElement.op_Explicit e : bool)

При этом вы можете написать:

let xe = XElement.Parse("<foo><baz>true</baz></foo>")
let bar = xe.Element (XName.op_Implicit "bar") |> elementToBool
let baz = xe.Element (XName.op_Implicit "baz") |> elementToBool

В F# Interactive это будет преобразовано в:

val bar : bool option = None 
val baz : bool option = Some true

Обратите внимание, что вы можете использовать найденную вами вспомогательную функцию, хотя она также понадобится вам и для вызовов op_Implicit.

С помощью функций конвертера это становится немного чище. Я адаптировал приведенный выше код для использования (слегка измененных версий) вашей вспомогательной процедуры конвертера:

let inline convi (x : ^a) : ^b = ((^a or ^b) : (static member op_Implicit : ^a -> ^b) x)
let inline conve (x : ^a) : ^b = ((^a or ^b) : (static member op_Explicit : ^a -> ^b) x)

let xe = XElement.Parse("<foo><baz>true</baz></foo>")
let elementToBool e =
  match e with
    | null -> None
    | e -> Some(conve e : bool)

let baz = "baz" |> convi |> xe.Element |> elementToBool
let bar = "bar" |> convi |> xe.Element |> elementToBool
person Reed Copsey    schedule 13.11.2013
comment
Спасибо за ответ. Я отмечу это как ответ. Я думаю, что с помощью (conve foo : Nullable‹bool›) ?= true синтаксис использования немного удобнее, хотя и не такой чистый, как синтаксис C#, но другая вспомогательная функция может это исправить. Помощник ?= находится (если я правильно помню) в пространствах имен System.Linq.Nullable (или около того). - person Bent Rasmussen; 14.11.2013
comment
Вы можете использовать XName.Get вместо XName.op_Implicit. - person luksan; 14.11.2013
comment
@luksan Хорошее замечание - я всегда забываю об этом (обычно использую XLinq только из C #) - person Reed Copsey; 14.11.2013