1
votes

It is well-known that class inheritance are "open" type-heirarchies and discriminated unions are "closed" type-heirarchies. However, while adding new subclasses is easy, adding new virtual functions requires modification of all the existing classes. Meanwhile, discriminated unions can add new functions easily.

             | inheritance | discriminated union
new type     | easy        | hard
new function | hard        | easy

OOP has been around enough that we've experienced the difficulty of "adding new methods to a type heirarchy," and in cases where "modify all the classes" is not a good option, we've come up with stuff like the Visitor pattern to add new functionality to existing types.

For example:

class Base       Base.f()    Base.g()
class A : Base   A.f()       A.g()
class B : Base   B.f()       B.g()

Because adding a virtual Base.h() is difficult, we use visitor pattern, so future functionality can be encapsulated. This is basically the inheritance-based analogue of a pattern-matched function!

class H : BaseVisitor { 
   visit(A)  { } 
   visit(B)  { }
}
// this looks really similar to:
let H something = 
    match something with 
    | A -> ..
    | B -> ..

TLDR: Is there a commonly seen abstraction (similar to the Visitor pattern) that deals with adding types to a discriminated union?

1

1 Answers

0
votes

If I understand your question correctly I would argue for the Bridge pattern. It lets you vary the interface/abstraction independently from its implementation, resulting in structurally flexibility. However, I have never had the need to use the bridge pattern.

Hope that helped :D