Initial add of the generic optimizer code

Before digging into this code, look at the Rules implemented at the bottom of DagOptimizer.

There are several TODOS here:

- [x] After I split the code into separate files, I started hitting a scala 2.9 compiler bug, that I don't hit in 2.10. I'll try to work around, or possibly hope that Twitter finally gets on 2.9 before we need this.

- [x] Tests tests tests. I played around at the repl, but clearly we need super hardcore tests for any optimization framework.

- [ ] Actually call this code from an existing platform.
does this or + need a type parameter? we are going to lose the type information in the returned HMap.

Generally, is the idea behind all this code, ie dealing in higher kinded types, to ensure that it's always possible to change what the N[_] can point at? Ie by not fixing it and keeping it open, we say "it might be a T1 here, but that can always change"?