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 don’t 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;

}