Functional Programming in C#

Learn how to write better C# code

Honest functions

Function honesty means that a function should convey all information about the possible input that it takes and the possible output that it produces. Honest function should always honor its signature. Consider the following example:

string GetPrefix(int age)
{
if (age < 0 || age > 150)
return null;
return age < 18 ? "child" : "adult";
}

The function signature is int -> string, which says that it gets an integer and returns a string, but in fact it will return null if the age is not valid. This is “dishonest” function, because it’s “hiding” something. Another example is:

int Divide(int x, int y)
{
return x / y;
}

The signature states that the function accepts two integers and returns another integer. But this is not the case in all scenarios. What happens if we invoke the function like Divide(1, 0)? The function implementation doesn't abide by its signature, throwing DivideByZero exception. That means this function is also "dishonest". How can we make this function an honest one? We can change the type of the y parameter (NonZeroInteger is a custom type which can contain any integer except zero):

int Divide(int x, NonZeroInteger y)
{
return x / y.Value;
}

The signature is int, NonZeroInteger -> int, which declares "Give me an integer and NonZeroInteger and I will give you back an integer". There is no other possible outcome(1). This function behaves as a mathematical function.

Another option is to change the return type:

int? Divide(int x, int y)
{
if (y == 0)
return null;
return x / y;
}

This version doesn't guarantee that it will return an integer for any possible input values.

1) There is the possibility of hardware failure, of the program running out of memory, and so on, but these are not intrinsic to the function implementation.

Continue reading: What is "pure" function

Resources: