Search
  • Arunav Sanyal

What are algebraic data types

So I love programming in Scala and do so at my daily job. As you may (or may not know) Scala comes with first class support for functional programming.


New folks joining our team are often at a loss on basic concepts of functional programming, as they have either not encountered it in school or have not encountered it in their day jobs (more often than not, it's both).


I have quite a few issues with folks whom I simply cannot communicate with in a professional setting due to this gaping lack of knowledge.


So I have decided to clarify basic, fundamental concepts of functional programming, starting with the one that creates the most "I have no idea what you are talking about" moments - Algebraic data types.


I will use Scala to illustrate my point across, but the concept is more generic than just a feature in. a programming language, it's an idea in Computer Science.


So what is an algebraic data type (also referred to from now on as ADT)?


An algebraic data type is a kind of composite data type, i.e. a type that is formed by composing other more primitive types.


That not terribly useful, so let me demonstrate a couple of examples

sealed trait Employee
case class Engineer(name: String, empId: Int, manager: Manager) extends Employee
case class Manager(name: String, empId: Int, reports: List[Employee]) extends Employee

This example has an OO flavor to it, but PLEASE do not look at it from an object oriented lens (and I will explain why shortly).


An employee has two subtypes Engineer and Manager. An employee can be either an engineer or a manager but not both. This is called a Sum Type (another way to think about it is that engineer and manager is a disjoint union).


Now the employee is a type that is a compound of (String, Int, Manager). This is called a product type (also called co-product). It's a product type because the set of all possible values of an employee is the cross product of the set of all possible names, employee Ids and Managers.


So how is this different from OO inheritance?


It's very important to note the type themselves do not "couple" with behavior. In traditional inheritance, a function like

def isManager(employee: Employee) = employee match {
    case _: Manager => true
    cae _ => false
}

is defined well outside of the class definitions, instead of the more traditional OO model of

interface Employee {
    public boolean isManager();
}

// Constructors, getters, setters ommitted. 
class Engineer implements Employee {
    private String name;
    private Int employeeId;
    private Manager manager; 
    
    @Override
    public boolean isManager {
        return false; 
    }
}

// Constructors, getters, setters ommitted.
class Manager implements Employee {
    private String name;
    private Int employeeId; 
    private Manager manager;
    
    @Override     
    public boolean isManager {         
        return true;     
    }
}

You technically can define isManager outside of the class definition, but then you are breaking traditional OO inheritance, and decoupling behavior from data.


ADTs only describe the data, and the behavior of the data is defined outside the context of the data itself.


Wait this smells like an enum?


I have gotten this question from tons of ignorant senior devs and managers, who have mostly programmed in imperative languages.


And there is some truth to this statement. Enums are a very special case of ADTs. While enums can describe sum types well, it cannot construct product types.


How is any of this useful to my life?


If you are a developer/software engineer who likes their one paradigm of programming, hates abstractions and loves boilerplate, this wont help you.


However if you like to learn new ideas, paradigms and concepts, you will immediately recognize that ADTs no longer shackle you to the OO model of marrying behavior with data.

23 views0 comments

©2020 by KhaliansMusings. Proudly created with Wix.com