This is follow up on my previous blog post:Adding xml strings in F# using computation expressions. The text is nearly identical, the language is C# instead of F#.
In some cases classes are enhanced wrappers of simple classes. For instance in .NET:
- DateTime is a point in time and provides, among others things, extra functionality related to representing date and time formats.
- XElement is an xml string and provides, among others things, checks to determine the validity of the xml string.
- Option can contain a value and can tell you if there is value available.
Sometimes you have to deal with underling class and reuse some of the functionality of the wrapper. In this case you could consider using LINQ. We first define the Return, Bind and SelectMany functions to create the required functions.
For details more details see:
- Functional Programming in C#: Classic Programming Techniques for Modern Projects (Wrox Programmer to Programmer)
- Real World Functional Programming: With Examples in F# and C#
- Monads in C#–1. Introduction
All excellent resources.
public static classXmlMonad
{
//monad
public staticXElement Return(this stringtext)
{
try
{
returnXElement.Parse(text);
}
catch(XmlException exc)
{
returnXElement.Parse(String.Format("<XmlException>{0}</XmlException>", exc.Message));
}
}
public staticXElement Bind(thisXElement el, Func<string, XElement> f)
{
try
{
returnf(el.ToString());
}
catch(XmlException exc)
{
returnXElement.Parse(String.Format("<XmlException>{0}</XmlException>", exc.Message));
}
}
public staticXElement SelectMany(thisXElement el, Func<string, XElement> f, Func<string, string, string> select)
{
returnel.Bind(text => f(text).Bind(x => select(text, x).Return()));
}
}
We can now define a add function that will xml elements by using a string manipulation:
private static XElement Add(XElement el1, XElement el2)
{
XElement result =
from x1 in el1
from x2 in el2
select x1.Substring(0, x1.LastIndexOf("<")) + x2.Substring(x2.IndexOf(">") + 1);
return result;
}
Add in action:
var el1 = XElement.Parse("<a><b>1</b><b>2</b></a>");
var el2 = XElement.Parse("<a><b>3</b><b>4</b></a>");
Console.WriteLine(string.Format("Add: {0}", Add(el1,el2)));
Results in:
When we change the xml into:
var el2 = XElement.Parse("<c><b>3</b><b>4</b></c>");
The result is: