Blue Theme Orange Theme Green Theme Red Theme
 
Home | Forums | Videos | Photos | Blogs | E-Books | Interviews | Jobs | Beginners | Training
 | Consulting  
Submit an Article 
 Login Close
User Id:
Password:
 
Forgot Password
Forgot Username
Why Register
 Jump to
Skip Navigation Links
TechnologyExpand Technology
WebsiteExpand Website
LeftbarAd
 Resources  
Close
 Our Network  
Close
Search :       Advanced Search »
Home » C# Language » Functional Programming with C# - Composition

Functional Programming with C# - Composition

In this article we'll look at using a couple different functional approaches to implementing a basic formula through composition including using monads.

Author Rank:
Technologies: .NET 1.0/1.1,Visual C# .NET
Total downloads : 96
Total page views :  7157
Rating :
 5/5
This article has been rated :  2 times
   Print Read/Post comments Post a comment  Rate  
   Email to a friend  Bookmark  Similar Articles  Author's other articles  
Download Files:
FunctionalSampleCode.zip
 
ArticleAd
Become a Sponsor



Introducing Our Formula.

For this article we'll be looking at computing the volume of a sphere given it's radius with the following formula:

4/3 * pi * (r ^ 3)

This is a very simple formula to implement and we could do (much) more complex things with the techniques we're about to look at.

Using Composition... The Not-So-Nice Way

To get started, let's build a series of simple methods that we can use as building blocks to construct our more complex sphere volume formula.

internal static Double Add(Double a, Double b)
{
    return a + b;
}

internal
static Double Subtract(Double a, Double b)
{
    return a - b;
}

internal
static Double Multiply(Double a, Double b)
{
    return a * b;
}

internal
static Double Divide(Double a, Double b)
{
    return a / b;
}

internal
static Double Power(Double a, Double b)
{
    return Math.Pow(a, b);
}

After we have these building blocks in place, we can compose our method with the functional blocks like the following method:

internal static Double VolumeOfSphere(Double r)
{
    // 4/3 ¶ r ^ 3
    return Multiply(Multiply(Divide(4, 3), Math.PI), Power(r, 3));
}

The resulting code is very ugly and would be difficult to maintain because it's hard to understand at a glance because as a result of the way our calls have to nest we really have to pay attention to the brackets.  It probably would have been better just to calculate our formula without our building blocks.  Keep in mind, we're going for an easier way to build our method up from smaller functional blocks.  This is a prefect example of a small bit of code that is functionally correct but not readable and so could actually be considered bad programming.

"Any fool can write code that a computer can understand. Good programmers write code that humans can understand."
-Martin Fowler et al, Refactoring: Improving the Design of Existing Code (p15), 1999

Making use of monads to make it prettier.

Think of a monad as a coding strategy or design pattern for building complex computations from simpler ones used as building blocks.  It is an abstraction of an existing type, in this case the CLR Double type, into something we are able to interact with functionally and that we can use to encapsulate more complex behaviors and hide them from the consumer code making it more human-readable.

We will define a Foo<> class that provides us with one level of abstraction from any existing CLR type.  Our implementation will be primarily using the Double type, but we could abstract any type we want.

public class Foo<T>
{
    public Foo(T pVal)
    {
        Value = pVal;
    }

    public Foo() { }

    public
T Value { get; set; }
}

We need to define our factory and utility methods in terms of our abstraction oo<Double>) instead of Double.  I have two different simple builder methods below, the standard Build() which is easily understandable, and the more LINQish notation "AsFoo()" builder extension method (similar to the LINQ AsQueryable()). We will also have constants that we can define like the Foo.PI which just wraps Math.PI.  Finally, we have our combinatory functions to add to our stew like add, subtract, multiply, divide and way to raise a Foo<Double> to a power.

public static class Foo
{
    internal static Foo<T> Build<T>(T pVal)
    {
        return new Foo<T>(pVal);
    }

    public static Foo<Double> AsFoo(this Double value)
    {
        return new     Foo<Double>(value);
    }

    private static readonly Foo<Double> m_pi = Foo.Build(Math.PI);

    public static Foo<Double> PI { get { return m_pi; } }

    public static Foo<Double> Add(this Foo<Double> source, Foo<Double> target)
    {
        return Foo.Build(source.Value + target.Value);
    }

    public static Foo<Double> Subtract(this Foo<Double> source, Foo<Double> target)
    {
        return Foo.Build(source.Value - target.Value);
    }

    public static Foo<Double> Multiply(this Foo<Double> source, Foo<Double> target)
    {
        return Foo.Build(source.Value * target.Value);
    }

    public static Foo<Double> Divide(this Foo<Double> source, Foo<Double> target)
    {
        return Foo.Build(source.Value / target.Value);
    }

    public static Foo<Double> Power(this Foo<Double> source, Foo<Double> target)
    {
        return Foo.Build(Math.Pow(source.Value, target.Value));
    }
}

So now that we have an abstracted type and a small utility library we can change the formula.  This (to me) is much more readable and would be much easier to maintain/modify because it reads just like the formula, from left to right and we don't have to pay as much attention to the brackets because each "step" is self contained and can be placed on a separate line.

internal static Double FooVolumeOfSphere(Double r)
{
    // 4/3 ¶ r ^ 3

    return (4.0).AsFoo()
        .Divide((3.0).AsFoo())
        .Multiply(Foo.PI)
        .Multiply(
            r.AsFoo()
            .Power((3.0).AsFoo()))
        .Value;
}

While this change is much nicer to look at it is still kind of noisy and the method really should be in our Foo<> utility library (and have input and output types of Foo<Double>).  This will help us make the algorithm implementation syntax even more succinct and pulls it farther away from the consumer code.

public static Foo<Double> SphereRadiusToVolume(this Foo<Double> radius)
{
    // 4/3 ¶ r ^ 3

    Foo<Double>
        four = (4.0).AsFoo(),
        three = (3.0).AsFoo();

    return four
        .Divide(three)          // 4/3
        .Multiply(Foo.PI)       // 4/3  ¶
        .Multiply(radius.Power(three)); // 4.3  ¶ (r ^ 3)
}

So now we can call it with the following code.  As you may have noticed, I switched the name just to make it more understandable when reading from left to right and also created placeholders for the values 3 (which is reusable) and 4.

Console.WriteLine("VolumeOfSphere: " + (10.0).AsFoo().SphereRadiusToVolume());

And as they say on those annoying late night tv commercials "wallah!". The complexity is separated out into our utility library. Now for the real sales pitch. "But wait! That's not all!  You also receive the ability to encapsulate complex combinatory behavior absolutely FREE!".

Let's say we want to protect our whole Foo<> abstraction layer from a DivideByZeroException which could happen in the Foo<Double>.Divide() method right now.  We need to find some other way to indicate there was a problem with our complex algorithm with out throwing expensive exceptions.

All we have to do is update Foo<> a bit to carry a flag to indicate if there was an error and maybe a string for the error description.

public class Foo<T>
{
    public Foo(T pVal, Boolean pHasErr, String pErr)
    {
        Value = pVal;
        HasError = pHasErr;
        Error = pErr;
    }

    public Foo(T pVal):this(pVal, false, String.Empty){}

    public Foo() { }

    public T Value { get; set; }
    public Boolean HasError { get; set; }
    public String Error { get; set; }

    #region
Overrides

    public override string ToString()
    {
        return HasError? Error: Value.ToString();
    }  

    public override int GetHashCode()
    {
        return HasError? this.GetHashCode(): Value.GetHashCode();
    }

    #endregion

}

And now we can carry errors through our calculations with one simple added utility method.  We'll pass the delegate to an extension method that takes two Foo<T>'s and combines them into one.  If either of the Foo<T>s has an error, we'll return it instead of executing the delegate.

public static Foo<T> Combine<T>(this Foo<T> source, Func<Foo<T>, Foo<T>, Foo<T>> combine, Foo<T> value)
{
    return source.HasError? source : value.HasError? value: combine(source, value);
}

So we now modify our method to take advantage of this error checking passing any problems through the call chain instead of throwing an exception.  The syntax is still just as "human-readable" as our previous implementation.

public static Foo<Double> SphereRadiusToVolume(this Foo<Double> radius)
{
    // 4/3 ¶ r ^ 3

    Foo<Double>
        four = (4.0).AsFoo(),
        three = (3.0).AsFoo();

    return four
        .Combine(Divide, three)
        .Combine(Multiply, Foo.PI)
        .Combine(Multiply, radius.Combine(Power, three));
}

And another really cool thing is that the consuming call looks exactly the same even though we are hiding much more complex error checking logic behind our abstracted Foo<Double>.SphereRadiusToVolume() method:

Console.WriteLine("VolumeOfSphere: " + (10.0).AsFoo().SphereRadiusToVolume());

Using this technique, we could build an entire library of functions to do whatever we want to do with our Foo<> that would be very easy to understand and consume and yet be able to hide much more complex logic underneath. This is a very useful weapon in the fight against complexity and composition can work for abstracting complex behavior or whenever you can use a divide-and-conquer approach to solving your coding puzzles. For instance, this would be a great approach for building a validation library on top of regular expressions or have a financial analysis project where you have to build dynamic formulas to do market forecasting.

Until next time,
Happy coding

Note: These examples were built with VisualStudio 2008 and use  the .NET 3.5 framework and so wont compile if you don't have the 3.5 runtime installed.


Login to add your contents and source code to this article
 [Top] Rate this article
 About the author
 
Matthew Cochran
Looking for C# Consulting?
C# Consulting is founded in 2002 by the founders of C# Corner. Unlike a traditional consulting company, our consultants are well-known experts in .NET and many of them are MVPs, authors, and trainers. We specialize in Microsoft .NET development and utilize Agile Development and Extreme Programming practices to provide fast pace quick turnaround results. Our software development model is a mix of Agile Development, traditional SDLC, and Waterfall models.
Click here to learn more about C# Consulting.
 
Introducing MaxV - one click. infinite control. Hyper-V Hosting from MaximumASP.
Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Dynamic PDF
ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
Boost the performance of your .NET applications
“ANTS Profiler took us straight to the specific areas of our code which were the cause of our performance issues." Terry Phillips, Sr. Developer, Harley-Davidson Dealer Systems. Download your free trial of ANTS Profiler.
Go.NET
Build custom interactive diagrams, network, workflow editors, flowcharts, or software design tools. Includes many predefined kinds of nodes, links, and basic shapes. Supports layers, scrolling, zooming, selection, drag-and-drop, clipboard, in-place editing, tooltips, grids, printing, overview window, palette. 100% implemented in C# as a managed .NET Control. Document/View/Tool architecture with many properties&events. Optional automatic layout.
Dundas Software
Dundas Chart for .NET is the most advanced .NET charting package available today.  With an extremely complete feature set, elegant architecture and easy implementation, Dundas Chart can quickly add advanced Charting functionality to enhance and transform ASP.NET and Windows Forms applications.  Whether you are implementing charting into internal projects, or building applications for clients, Dundas Chart offers advanced technology and advanced results to get the most out of data.
 
   Print Read/Post comments Post a comment  Rate  
   Email to a friend  Bookmark  Similar Articles  Author's other articles  
Download Files:
FunctionalSampleCode.zip
 
 Post a Feedback, Comment, or Question about this article
Subject:  
Comment:  
ArticleAd
Become a Sponsor
Latest Comments:
Subject Posted By Posted On

 Hosted by MaximumASP  |  Found a broken link?  |  Contact Us  |  Terms & conditions  |  Privacy Policy  |  Site Map  |  Suggest an Idea  |  Media Kit
Current Version: 5.2009.6.2
 © 1999 - 2009  Mindcracker LLC. All Rights Reserved