ADT-like polymorphism in Java (without altering class)

Posted by ffriend on Stack Overflow See other posts from Stack Overflow or by ffriend
Published on 2012-10-05T20:53:42Z Indexed on 2012/10/05 21:37 UTC
Read the original article Hit count: 485

In Haskell I can define following data type:

data Tree = Empty
      | Leaf Int
      | Node Tree Tree

and then write polymorphic function like this:

depth :: Tree -> Int
depth Empty = 0
depth (Leaf n) = 1
depth (Node l r) = 1 + max (depth l) (depth r)

In Java I can emulate algebraic data types with interfaces:

interface Tree {}
class Empty implements Tree {}
class Leaf implements Tree { int n; }
class Node implements Tree { Tree l; Tree r; }

But if I try to use Haskell-like polymorphism, I get an error:

int depth(Empty node) {
    return 0;
}
int depth(Leaf node) {
    return 1;
}
int depth(Node node) {
    return 1 + Math.max(depth(node.l), depth(node.r));   // ERROR: Cannot resolve method 'depth(Tree)'
}

Correct way to overcome this is to put method depth() to each class. But what if I don't want to put it there? For example, method depth() may be not directly related to Tree and adding it to class would break business logic. Or, even worse, Tree may be written in 3rd party library that I don't have access to. In this case, what is the simplest way to implement ADT-like polymorpism?

Just in case, for the moment I'm using following syntax, which is obviously ill-favored:

int depth(Tree tree) {
    if (tree instanceof Empty) depth((Empty)tree)
    if (tree instanceof Leaf) depth((Leaf)tree);
    if (tree instanceof Node) depth((Node)tree); 
    else throw new RuntimeException("Don't know how to find depth of " + tree.getClass());
}

© Stack Overflow or respective owner

Related posts about java

Related posts about haskell