5

In C# I can express this:

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

How can this be expressed in F#?

Edit: I did find this helper function

let inline conv (x : ^a) : ^b = ((^a or ^b) : (static member op_Explicit : ^a -> ^b) (x))
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Bent Rasmussen
  • 5,538
  • 9
  • 44
  • 63
  • 2
    See here for options: http://www.trelford.com/blog/post/F-XML-Comparison-(XElement-vs-XmlDocument-vs-XmlReaderXmlWriter-vs-Discriminated-Unions).aspx – N_A Nov 13 '13 at 22:53

2 Answers2

6

Unfortunately, XLinq relies heavily on implicit and explicit conversions, which makes things a bit difficult.

You can make a routine to convert from an XElement to a bool option:

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

With this, you can write:

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

In F# Interactive, this will convert to:

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

Note that you can use the helper function you found, though you'd also need one for the op_Implicit calls as well.

Using the converter functions this becomes a bit cleaner. I've adapted the code above to use (slightly modified versions of) your converter helper routine:

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
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Thanks for the answer. I'll mark this as a reply. I think using (conve foo : Nullable) ?= true is slightly nicer usage syntax though - although not quite as clean as the C# syntax - but another helper function could fix that. The ?= helper is (if I recall correctly) in the System.Linq.Nullable namespaces (or thereabout). – Bent Rasmussen Nov 14 '13 at 12:20
  • 3
    You can use `XName.Get` instead of `XName.op_Implicit`. – luksan Nov 14 '13 at 16:39
  • @luksan Good point - I always forget about that one (tend to only use XLinq from C#) – Reed Copsey Nov 14 '13 at 17:57
0

There's now better support for implicit conversions in F# 6

https://learn.microsoft.com/en-us/dotnet/fsharp/whats-new/fsharp-6#first-class-support-for-net-style-implicit-conversions

jrequejo
  • 195
  • 1
  • 6