Search code examples
f#linq-to-xmloperator-keywordxelementexplicit-conversion

F# and explicit conversion in LINQ to XML


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))

Solution

  • 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