In object-oriented languages, I think the closest analogue to sum types are type hierarchies. It's more verbose and cumbersome, but you can get the same effect through dynamic polymorphism. Consider the example from the post:
type AST = Expr of ...
| Stmt of ...
| Comment of ...
let rec evaluate e =
match e with
| Expr # evaluate the ... of an Expr
| Stmt # ditto
| Comment # ditto
In the object-oriented world, I think this most naturally maps to (forgive me for not using Python syntax; I love Python, but I rarely do much OO in it):
class AST {
public:
virtual bool evaluate() = 0; // again, forgive the C++ syntax
};
class Expr: public AST {
public:
virtual bool evaluate()
{
// Expr specific evaluate code
}
};
class Stmt: public AST {
public:
virtual bool evaluate()
{
// Ditto
}
};
class Comment: public AST {
public:
virtual bool evaluate()
{
// Ditto
}
};
As seanmcdirmid points out, this is
not the same, as the discrimination happens at runtime. But, I think it's the closest analogue. Also note that in the algebraic data-type world, we normalize on functions. That is, what to do in order to
evaluate any given AST exists in the one evaluate function. But, in the OO world, we normalize on the
types; how we evaluate a given AST is spread out over the many evaluate methods.