Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why ADTs are good and Inheritance is bad?

Tags:

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.

like image 210
one-zero-zero-one Avatar asked Jul 17 '10 14:07

one-zero-zero-one


People also ask

Is it bad to use inheritance?

Using inheritance for behavioral composition and polymorphism is a common piece of knowledge you find in every OOP 101 book or blog post. Sadly, it's wrong. Using inheritance is not the only way to extend a class behavior, but definitely is the most dangerous and harmful one.

Why composition is better than inheritance in java?

One more benefit of composition over inheritance is testing scope. Unit testing is easy in composition because we know what all methods we are using from another class. We can mock it up for testing whereas in inheritance we depend heavily on superclass and don't know what all methods of superclass will be used.

Why is multiple inheritance not recommended?

The reason behind this is to prevent ambiguity. Consider a case where class B extends class A and Class C and both class A and C have the same method display(). Now java compiler cannot decide, which display method it should inherit. To prevent such situation, multiple inheritances is not allowed in java.

How do you avoid inheritance in programming?

While one of Java's strengths is the concept of inheritance, in which one class can derive from another, sometimes it's desirable to prevent inheritance by another class. To prevent inheritance, use the keyword "final" when creating the class.


2 Answers

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.

like image 68
Tomas Petricek Avatar answered Nov 18 '22 20:11

Tomas Petricek


Tomas Petricek has got the fundamentals exactly right; you might also want to look at Phil Wadler's writing on the "expression problem".

There are two other reasons some of us prefer algebraic data types over inheritance:

  • Using algebraic data types, the compiler can (and does) tell you if you have forgotten a case or if a case is redundant. This ability is especially useful when there are many more operations on things than there are kinds of thing. (E.g., many more functions than algebraic datatypes, or many more methods than OO constructors.) In an object-oriented language, if you leave a method out of a subclass, the compiler can't tell whether that's a mistake or whether you intended to inherit the superclass method unchanged.

  • This one is more subjective: many people have noted that if inheritance is used properly and aggressively, the implementation of an algorithm can easily be smeared out over a half a dozen classes, and even with a nice class browser at can be hard to follow the logic of the program (data flow and control flow). Without a nice class browser, you have no chance. If you want to see a good example, try implementing bignums in Smalltalk, with automatic failover to bignums on overflow. It's a great abstraction, but the language makes the implementation difficult to follow. Using functions on algebraic data types, the logic of your algorithm is usually all in one place, or if it is split up, its split up into functions which have contracts that are easy to understand.


P.S. What are you reading? I don't know of any responsible person who says "ADTs good; OO bad."

like image 34
Norman Ramsey Avatar answered Nov 18 '22 20:11

Norman Ramsey