Search code examples
javaoopprogramming-languageshaskellfunctional-programming

Why ADTs are good and Inheritance is bad?


I am a long time OO programmer and a functional programming newbie. From my little exposure algebraic data types only look like a special case of inheritance to me where you only have one level hierarchy and the super class cannot be extended outside the module.

So my (potentially dumb) question is: If ADTs are just that, a special case of inheritance (again this assumption may be wrong; please correct me in that case), then why does inheritance gets all the criticism and ADTs get all the praise?

Thank you.


Solution

  • I think that ADTs are complementary to inheritance. Both of them allow you to create extensible code, but the way the extensibility works is different:

    • ADTs make it easy to add new functionality for working with existing types
      • You can easily add new function that works with ADT, which has a fixed set of cases
      • On the other hand, adding new case requires modifying all functions
    • Inheritance makes it easy to add new types when you have fixed functionality
      • You can easily create inherited class and implement fixed set of virtual functions
      • On the other hand, adding a new virtual function requires modifying all inherited classes

    Both object-oriented world and functional world developed their ways to allow the other type of extensibility. In Haskell, you can use typeclasses, in ML/OCaml, people would use dictionary of functions or maybe (?) functors to get the inhertiance-style extensibility. On the other hand, in OOP, people use the Visitor pattern, which is essentially a way to get something like ADTs.

    The usual programming patterns are different in OOP and FP, so when you're programming in a functional language, you're writing the code in a way that requires the functional-style extensibility more often (and similarly in OOP). In practice, I think it is great to have a language that allows you to use both of the styles depending on the problem you're trying to solve.