F#: Wrapping .NET library calls
I've been spending a bit of time writing some code to parse the xml of my Feedburner RSS feed and create a graph to show both the daily and weekly average subscribers which you can't currently get from the Feedburner dashboard.
One thing which I found while doing this is that calls to the .NET base class library don't seem to fit in that well with the way that you would typically compose functions together in F#.
For example one of the first things I wanted to do was print the date and the circulation count to the console which I originally did like this:
open System.IO open System.Net open Microsoft.FSharp.Control open System.Xml.Linq open System let xName value = XName.Get value // GetXml is a function of type string -> string let GetFeedBurnerStats url = let feedBurnerXml = GetXml url |> XDocument.Parse feedBurnerXml.Descendants(xName "entry") |> Seq.map (fun x -> x.Attribute(xName "circulation"), x.Attribute(xName "date")) |> Seq.iter (fun x -> printfn "%s %s" (fst x).Value (snd x).Value)
It's quite annoying that we need to store the XDocument as a value before being able to call one of the methods on it to get the data that we want.
I realised that if I created a function which took in the element whose descendants I wanted to find and the XDocument I could then call the 'XDocument.Descendants()' method inside that function:
1 2 3 4 5 6 7 8 9 | let xName value = XName.Get value let GetDescendants element (xDocument:XDocument) = xDocument.Descendants(xName element) let GetFeedBurnerStats = GetXml >> XDocument.Parse >> GetDescendants "entry" >> Seq.map (fun x -> x.Attribute(xName "circulation"), x.Attribute(xName "date")) >> Seq.iter (fun x -> printfn "%s %s" (fst x).Value (snd x).Value) |
Since we no longer need to store the intermediate step of creating the XDocument we can now just chain together the functions using the functional composition operator instead of the forward operator.
We can also do this with the calls to 'Attribute' in the 'Seq.map' function on line 9 which helps simplify the code around there.
1 2 3 4 5 6 7 8 9 10 | let xName value = XName.Get value let GetDescendants element (xDocument:XDocument) = xDocument.Descendants(xName element) let GetAttribute element (xElement:XElement) = xElement.Attribute(xName element) let GetFeedBurnerStats = GetXml >> XDocument.Parse >> GetDescendants "entry" >> Seq.map (fun x -> GetAttribute "circulation" x, GetAttribute "date" x) >> Seq.iter (fun x -> printfn "%s %s" (fst x).Value (snd x).Value) |
F#: Wrapping .NET library calls – Mark Needham…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
DotNetShoutout
14 Jul 09 at 9:37 pm
[...] continued using the idea of creating F# functions to wrap C# style method calls with the 'Entries' function which delegates to the 'Entries' property on 'FeedBurnerApi' which [...]
F#: Active patterns for parsing xml at Mark Needham
19 Jul 09 at 12:16 pm
[...] Mark Needham has posted some good F# articles: Feedburner graph creator | Wrapping .NET library calls [...]
Weekly Link Post 102 « Rhonda Tipton’s WebLog
20 Jul 09 at 10:52 am
[...] of the things I've noticed recently in my playing around with F# is that when we decide to wrap calls to the .NET DateTime methods there is a need to be quite careful that we are wrapping those calls [...]
F#: Values, functions and DateTime at Mark Needham
25 Jul 09 at 2:11 pm
[...] previously written about wrapping .NET library calls and I was doing this quite a lot when I started writing this [...]
F#: Word Count – A somewhat failed attempt at Mark Needham
18 Dec 09 at 3:00 am