It's fair to summarize classes in OOP as "product types with functions." However, couldn't there be something like "sum types with functions"? How would inheritance work with them?

I'm trying to scout if anybody has considered this question before in language design.

  • $\begingroup$ Note that many / most OOP languages even lack a proper sum type. In Java, for instance, you can try to simulate it with subtyping and obtain sum elimination using if (x instanceof ...) and casts, which is quite bad in OOP. Or, better, you can Church-encode sum types with polymorphic types (generics and visitor pattern, in modern OOP lingo) and obtain elimination without casts. Some OOP languages do have sums, though: Scala has sealed traits, Swift (IIRC) has enums. $\endgroup$
    – chi
    Aug 3, 2017 at 8:22

2 Answers 2


The key to remember is that there's a sort of dualism between functional sum types, and OOP implementations of a superclass or interface:

  • Sum types require the variants for a type to be specified up front, and for every operation, requires that we specify the operation for each variant. Adding a new operation is easy, adding a variant requires refactoring all functions.

  • OOP requires that we specify the operations for a type up front, and each implementation/subclass specifies its own implementation for each operation. Adding a new variant is easy, but adding a new operation requires refactoring in each subclass.

In each case, we have all possible pairs of variants and operations, but we differ on how we group them: all the implementations for variants in an operation together, or all the operations for a variant together.

It's fair to summarize classes in OOP as "product types with functions."

At its most barebones version, maybe. But this ignores any subtyping structure. Many versions of OOP are much richer, with interfaces being analogous to existential types.

As for the question of "what if we just did sum-types with functions", this would be pretty boring. You would specify a bunch of variants for your type, and then a bunch of operations your type, which would have to specify an implementation for each variant.

This is basically just a normal OOP type with a single member variable that's a sum-type, and a bunch of functions operating on that variable.

  • $\begingroup$ Very interesting to consider this dualism! Of course, in functional languages that have typeclasses (or traits, which are similar), we have the best of both worlds: Sum types are used when there is a closed set of variants, meaning that we can easily add a new operation, whereas we can use a typeclass if there is an open set of variants. $\endgroup$
    – Qqwy
    Nov 13, 2018 at 7:37

Hm, I don't have the points to comment, but are you sure you mean that?

Classes already are a sort of sum type: polymorphism means that a variable declared to refer to something of type "A" could instead refer to an object of any of its subclasses B, C, etc. - so this is like a tagged union.

And of course, as you say, objects are also product types, in that in most imperative languages, they're jumped-up record types.

Anyway. If this isn't what you mean, it might be worth looking in one of the texts on theory of OO languages to see if what you're after has been covered – perhaps Abadi and Cardelli's Theory of Objects might have something.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.