Is this functional code? Dr.T. Reply.

2007/01/31

Tags: C#

This would be a functional approach:

CountWithPrevious : [‘a] => (a => a => bool) => int // type of the function
CountWithPrevious [] _                    = 0
CountWithPrevious [_]  _                  = 0
CountWithPrevious [prev, val | tail] pred = CountWithPrevious [val | tail] + (pred val prev ? 1 : 0)

Some observations:

_” is used as wildcard argument – matches any value that you don’t need a name for. [ x,y,z | t ] are pattern matching over lists – here x,y and z get bound to the first elements and t is the rest of the list. Both CountWithPrevious and the passed-in pred are curried – they take two arguments but one at a time. The CountWithPrevious function is defined with pattern matching – at runtime it searches through the definitions until one matches. The type declaration is optional – the compiler can figure out the type from the last case of the function. In C# we don’t have pattern matching and currying, and so would probably need a helper function.

public static int CountWithPrevious<T>(IEnumerable<T> en, PredWithPrevious pred) {
IEnumerator<T> rest = en.GetEnumerator();

if (rest.MoveNext()) return Helper(rest.Current,rest,pred);

else return 0;

}

private static int Helper<T>(T prev, IEnumerator<T> rest, PredWithPrevious pred) {

if (rest.MoveNext()) {

T val = rest.Current;

return Helper(val,rest,pred) + (pred(val,prev) ? 1 : 0);

} else return 0;

}

We could simulate local functions with lambdas so that we dont need to pass pred, prev and T along:

public static int CountWithPrevious<T>(IEnumerable<T> en, PredWithPrevious pred) {
IEnumerator<T> rest = en.GetEnumerator();

Func<T,int> helper = prev => {

if (rest.MoveNext()) {

T val = rest.Current;

return Helper(val) + (pred(val,prev) ? 1 : 0);

} else return 0;

};

if (rest.MoveNext()) return Helper(rest.Current);

else return 0;

}
comments powered by Disqus Updated: 2019-01-23 11:41:32 +0100 +0100, Version: 6668e21