I am currently learning F# and functional programming in general (from a C# background) and I have a question about using .net CLR objects during my processing.
The best way to describe my problem will be to give an example:
let xml = new XmlDocument()
|> fun doc -> doc.Load("report.xml"); doc
let xsl = new XslCompiledTransform()
|> fun doc -> doc.Load("report.xsl"); doc
let transformedXml =
new MemoryStream()
|> fun mem -> xsl.Transform(xml.CreateNavigator(), null, mem); mem
This code transforms an XML document with an XSLT document using .net objects.
Note XslCompiledTransform.Load works on an object, and returns void.
Also the XslCompiledTransform.Transform requires a memorystream object and returns void.
The above strategy used is to add the object at the end (the ; mem) to return a value and make functional programming work.
When we want to do this one after another we have a function on each line with a return value at the end:
let myFunc =
new XmlDocument("doc")
|> fun a -> a.Load("report.xml"); a
|> fun a -> a.AppendChild(new XmlElement("Happy")); a
Is there a more correct way (in terms of functional programming) to handle .net objects and objects that were created in a more OO environment?
The way I returned the value at the end then had inline functions everywhere feels a bit like a hack and not the correct way to do this.
Any help is greatly appreciated!
One of the great benefits of F# is that it allows you to mix the functional programming style with other styles (namely object-oriented and imperative). Since most of the .NET libraries are object-oriented and imperative, the best way to access .NET functionality from F# is to simply use the imperative features of F#. This means that when working with .NET objects, the idiomatical F# code will look almost like C#.
EDIT: The following slightly modified example shows how to wrap XSL transformation into a function that takes the name of the input file and a name of the xsl file. It returns the
MemoryStreamwhere the output was written:And the second example:
This doesn’t mean that you’re turning away from the functional style in any way – there are many opportunities to use functional style when working with .NET classes. For example you can use higher-order functions like
Seq.filterandSeq.map(or sequence expressions) to process collections of data (or XML elements). You can still write abstractions using higher-order functions.The
System.Xmlnamespace is very imperative, so there isn’t much space for functional style. However, the code that generates the data that you store in XML can be fully functional. It may be worth looking at the LINQ to XML classes (in .NET 3.5+), because they are designed in a much more functional-programming-friendly fashion (as they are supposed to work well with LINQ, which is also functional).