# Thinking Functionally: Function Signatures

Declarative functions signatures are just good practice whether you're writing imperatively or functionally. On any suitably large project - with multiple developers - it's impossible to know everything that goes on within a function (and you shouldn't have to know). Documentation can only take you so far, and tends to rot over time. So we need the signature of the function to tell us what's what.

For example:

`    DateTime CreateDate(int a, int b, int c);`

Clearly that's not as declarative as:

`    DateTime CreateDate(int year, int month, int day);`

We're all used to using names to communicate with other devs about our intentions. Names are a pretty crude tool for constraining data. The compiler won't do anything if you provide a `month` with the number `13`. Ideally we need this:

`    DateTime CreateDate(Year year, Month month, Day day);`

But creating a new-type for every usage of an `int` (or any unconstrained base-type) would be extremely tedious.

## Constrained types

Language-ext provides three classes to help: `NewType`, `NumType`, `FloatType`. `NewType` is the most general case, `NumType` would be used for integer number types (`int`, `short`, `long`, `BigInteger`, etc.), and `FloatType` is used for floating point number types (`float`, `double`, `decimal`, etc.).

So let's create `Year`, `Month`, `Day`:

```    public class Year : NumType<Year, TInt, int>
{
Year(int x) : base(x) { }
}

public class Month : NumType<Month, TInt, int>
{
Month(int x) : base(x) { }
}

public class Day : NumType<Day, TInt, int>
{
Day(int x) : base(x) { }
}```

We can now create typed values:

```    var day = Day.New(1);
var month = Month.New(1);
var year = Year.New(2000);```

But you can't assign a `Day` to a `Month`, or a `Month` to a `Year`, because they're not the same types.

What about constraints. We can just use constructors:

```    public class Year : NumType<Year, TInt, int>
{
Year(int x) : base(x)
{
if(x < 1970 || x > 2050) throw new ArgumentException("Invalid year");
}
}

public class Month : NumType<Month, TInt, int>
{
Month(int x) : base(x)
{
if(x < 1 || x > 12) throw new ArgumentException("Invalid month");
}
}

public class Day : NumType<Day, TInt, int>
{
Day(int x) : base(x)
{
if(x < 1 || x > 31) throw new ArgumentException("Invalid day");
}
}```

Or we can do it declaratively:

```    using LanguageExt.ClassInstances;
using LanguageExt.ClassInstances.Const;
using LanguageExt.ClassInstances.Pred;

public class Year : NumType<Year, TInt, int, Range<TInt, int, I1970, I2050>>
{
Year(int x) : base(x) { }
}

public class Month : NumType<Month, TInt, int, Range<TInt, int, I1, I12>>
{
Month(int x) : base(x) { }
}

public class Day : NumType<Day, TInt, int, Range<TInt, int, I1, I31>>
{
Day(int x) : base(x) { }
}```

It's a little awkward to use the declarative style, so I would understand if you prefer the constructor approach. To see what predicates are available for validation check the: `LanguageExt.ClassInstances.Pred` namespace and the constants are in `LanguageExt.ClassInstances.Const`. You can build your own predicates by deriving from `Pred<A>` and your own constants by deriving from `Const<A>`.

The benefits however are:

• You can create re-usable validators
• When you find a type in your source code and select 'Go To Definition' you can see the predicate that's being used. No need to look at the source

The end result is a function that looks like this:

`    DateTime CreateDate(Year year, Month month, Day day);`

And that communicates so much to the consumer of that function it's hard to go wrong, but even if you do, the type system picks it up.

You may have noticed that you could have a date which is 31st Feb. This doesn't deal with composite validation, so you still need to do that.

There are other areas these predicates in the generics can be used. For example:

```    int DoSomethingWithAList(Lst<int> list)
{
if(list.IsEmpty) throw new ArgumentException("List must not be empty");
...
}```

The range on a list is another example where we can't tell from the signature what's going on.

Try this:

```    int DoSomethingWithAList(Lst<NonEmpty, int> list)
{
// List can't ever be empty here
}```

The predicate enforces the rule and it's embedded in the type. So wherever you work with a list the `NonEmpty` attribute is following it around. The type system is communicating with you.

You could also do:

```    int DoSomethingWithAList(Lst<MaxCount<I100>, int> list)
{
// List must have 100 or fewer items
}

int DoSomethingWithAList(Lst<CountRange<I1, I100>, int> list)
{
// List must have 1 - 100 items.
}```

By the time you get to a function that takes a list or something like that, you could be many methods and stack frames away from the source of the error. By using declarative types then you catch the issues and declare your intent when you create the list.

## Signatures that talk

Let's look again at our `CreateDate` example. What happens when I pass '31st Feb' as a date? We must assume that it throws an exception.

`    DateTime CreateDate(Year year, Month month, Day day);`

`    string CreateDateString(Year year, Month month, Day day);`

This is a function that appears to create a formatted date string based on the parameters. If we give an invalid date, do we:

• Get a `null` return value?
• Get an exception thrown?

The only way to know is from documentation or source code. We don't want to have to read the source code for every function we work with, so we need the signature to talk to us.

In general in functional programming it's better to avoid throwing exceptions (because exceptions break the whole idea of mathematical expressions and send us back to `goto` land), and instead pass back a result that indicates failure. In language-ext there are a number of types that do this:

• `Option<A>`
• `OptionUnsafe<A>`
• `OptionAsync<A>`
• `Either<L, R>`
• `EitherUnsafe<L, R>`
• `Try<A>`
• `TryOption<A>`
• `TryAsync<A>`
• `TryOptionAsync<A>`

So how do these work? Let's start with the `CreateDateString` example:

```    Try<string> CreateDateString(Year year, Month month, Day day) => () =>
new DateTime(year.Value, month.Value, day.Value).ToShortDateString();```

What we're doing here is no validation ourselves, but relying on the validation of `DateTime`. `DateTime` however throws exceptions, which we don't want. So instead we return a `Try<string>`. `Try<A>` is a delegate type, and so we wrap this: `new DateTime(year.Value, month.Value, day.Value).ToShortDateString()` in a lambda (notice the `=> () =>` at the end of the first line.

Next we make use of the extension methods for `Try<string>` to work with the value:

```    Try<string> date = CreateDateString(Year.New(2000), Month.New(2), Day.New(30));

string result = date.IfFail("Invalid date");```

This is great, we can now handle the failure gracefully, and at the point where we know more about it. We can also pattern match on the result. The result has two possible states `Succ` for success, and `Fail` for failure:

```    Try<string> date = CreateDateString(Year.New(2000), Month.New(2), Day.New(30));

string result = date.Match(
Succ: dt => \$"The date is {dt}",
Fail: ex => \$"Invalid date ({ex.Message})"
);```

This is using named arguments to specify the handlers for the patterns. We can now post-process the value when it succeeds and craft a useful default when it fails.

The most important thing about these types is that you can't physically get at the `string` value until you've confirmed that it exists. So there's no `null` reference exceptions and no doubt in the programmers mind whether there are bugs in the code they're writing.

What about working with multiple functions that could fail? Let's change our `CreateDateString` example to the original `CreateDate` example. In fact, why not get creative with this... let's make it an extension method for the tuple `(Year, Month, Day)`.

```    public static class TupleExt
{
public static Try<DateTime> ToDate(this (Year year, Month month, Day day) date) => () =>
new DateTime(date.year.Value, date.month.Value, date.day.Value);
}```

So now we have an extension method that will turn a tuple into a `Try<DateTime>`:

Let's try working with two `Try<DateTime>` by getting the `TimeSpan` between them:

```    Try<DateTime> fromDate = (Year.New(2000), Month.New(1), Day.New(1)).ToDate();
Try<DateTime> toDate = (Year.New(2017), Month.New(5), Day.New(20)).ToDate();

TimeSpan result = fromDate.Match(
Succ: begin =>
toDate.Match(
Succ: end => end - begin,
Fail: ex  => TimeSpan.Zero),
Fail: ex => TimeSpan.Zero);```

Euurggh! Ugly right!? Nobody want to do this. And what if we had more than two items? It would very quickly become a mess of nested lambdas.

It just so happens that the behaviour from the example above is also an example of monadic binding. Which means we can use LINQ to achieve the same ends (but in a much more attractive manner):

```    var result = from begin in fromDate
from end in toDate
select end - begin;```

So what is the `result` here? It's a `Try<TimeSpan>`. We're still in our `Try` context. So if we want to invoke the expression to get the value we can still do:

`    TimeSpan span = result.IfNone(TimeSpan.Zero);`

In general it's better to stay in context when working with monadic types. Using `Match`, `IfNone`, `IfFail`, etc. should be a last resort when you need to get a concrete value out. Even then it can be better to call `Iter(x => ...)` where `x` is the bound value and `...` is the code that works on it. Or `Map(x => ...)` which is the same as `Iter` but expects a return value (which will be re-bound in the monadic type).

`Try<A>` is to handle exceptional behaviour (code that might throw exceptions), but not all error values are exceptional. Some are known:

```    int ParseInt(string value) =>
Int32.TryParse(value, out var result)
? result
: 0;```

That code will never throw an exception, but returning `0` as a default isn't a great solution. So let's move on to `Option<A>`.

```    using static LanguageExt.Prelude;

Option<int> ParseInt(string value) =>
Int32.TryParse(value, out var result)
? Some(result)
: None;```

Anyone looking at this signature can't fail to see that the result is optional:

`    Option<int> ParseInt(string value)`

It also indicates that the function is not likely to throw exceptions (if it does, then it will be truly exceptional!).

Usage follows a similar path to `Try<A>`:

```    Option<int> result = from a in ParseInt("10")
from b in ParseInt("20")
from c in ParseInt("30")
select a + b + c;

// Some(60)```

TBC

NEXT: What is LINQ really?

##### Clone this wiki locally
You can’t perform that action at this time.
Press h to open a hovercard with more details.