Functional Programming – What Problem Do Algebraic Data Types Solve?

algebraic-data-typefunctional programming

Fair warning, I'm new to functional programming so I may hold many bad assumptions.

I've been learning about algebraic types. Many functional languages seem to have them, and they are fairly useful in conjunction with pattern matching. However, what problem do they actually solve? I can implement a seemingly (sort-of) algebraic type in C# like this:

public abstract class Option { }
public class None : Option { }
public class Some<T> : Option
{
    public T Value { get; set; }
}

var result = GetSomeValue();
if(result is None)
{
}
else
{
}

But I think most would agree this is a bastardization of object oriented programming, and you shouldn't ever do it. So does functional programming just add a cleaner syntax that makes this style of programming seem less gross? What else am I missing?

Best Answer

Classes with interfaces and inheritance present an open world: Anyone can add a new kind of data. For a given interface, there may be classes implementing it all over the world, in different files, in different projects, at different companies. They make it easy to add cases to the data structures, but because the implementations of the interface are decentralized, it is hard to add a new method to the interface. Once an interface is public, it is basically frozen. Nobody knows all the possible implementations.

Algebraic data types are the dual to that, they are closed. All the cases of the data are listed in one place and operations not only can list the variants exhaustively, they are encouraged to do so. Consequently writing a new function operating on an algebraic data type is trivial: Just write the damn function. In return, adding new cases is complicated because you need to go over basically the entire code base and extend every match. Similar to the situation with interfaces, in the Rust standard library, adding a new variant is a breaking change (for public types).

These are two sides of the expression problem. Algebraic data types are an incomplete solution to them, but so is OOP. Both have advantages depending on how many cases of data there are, how often those cases change, and how frequently the operations are extended or changed. (Which is why many modern languages provide both, or something similar, or go straight for more powerful and more complicated mechanisms that try to subsume both approaches.)