Add a (more constrained) API for expressing filters on columns

This is to support predicate push down, which will take advantage of these constrained filter predicates.
This will need to be reconciled with the column filters currently in the `parquet.filter` package, but I wanted to get feedback on this first.

Sample usage in java:
```
// if you lie, and column "a.b.c" isn't an int column, we won't know until runtime. 
Column<Integer> abc = column("a.b.c"); 
Column<Double> xyz = column("x.y.z");

FilterPredicate predicate =
      and(not(or(eq(abc, 7), eq(abc, 17))), gtEq(xyz, 100.0));
```

Sample usage in scala:
```
val abc = Column[Int]("a.b.c")
val xyz = Column[Double]("x.y.z")
val predicate = !((abc === 7) || (abc === 17)) && (xyz >= 100.0)
```
My initial thought was that this would be a way to represent / store a predicate, and then we could get more fancy on how to execute it (via code generation, expression simplification, etc)

That said, we'd have to build all that, so maybe making this more explicit would allow for easier optimizations. 

When these predicates are applied to row groups, speed isn't a concern. But they will have to be applied again to the values, and there speed probably is a concern.

What do you think? It's easy to add in tokens for notEq, ltEq and so on.