Functional programming in C Sharp
Dec 18, 2016
2 minute read

Many .NET programmers were introduced to functional programming through the powerful System.Linq library which contains a collection of higher-order functions designed for working with sets:

var fastCarModels = cars
    .Where(x =>
        x.Weight < 2000 &&
        x.HorsePower > 300 &&
        x.IsRoadLegal)
    .Select(x => x.Model);

Linq is one of many powerful .NET features which was borrowed from functional concepts. Here are some examples of how we can borrow functional concepts and reuse them in C#.

Partial application

Partial application allows us to pass some (but not all) arguments to a function, producing a new function which can accept the remaining arguments:

public static Func<T2, TRet> PartiallyApply<T1, T2, TRet>(
    Func<T1, T2, TRet> fn,
    T1 arg1)
{
    return arg2 => fn(arg1, arg2);
}

Memoization

Memoization (or caching) allows us to cache the result of a function using the function’s arguments as a caching key.

public static Func<T1, T2, TRet> Memoize<T1, T2, TRet>(Func<T1, T2, TRet> fn)
{
    var cache = new Dictionary<Tuple<T1, T2>, TRet>();

    return (arg1, arg2) =>
    {
        var key = Tuple.Create(arg1, arg2);
        TRet value;
        if (!cache.TryGetValue(key, out value))
        {
            value = fn(arg1, arg2);
            cache.Add(key, value);
        }
        return value;
    };
}

Don’t overdo it

When working in a primarily OO language don’t try to shoehorn in functional concepts at every opportunity. Use them judiciously and ensure the design clearly demarcates where OO concepts end and FP concepts begin. Too much FP in an OO language can lead to poorly maintainable code.

Check out language-ext for a pre-built library of functional programming concepts.


Back to posts