Make TypedPipe immutable

Let's really look carefully at this. This was an attempt at a minimal change that would be source-code compatible.

Some questions:

1. should TypedPipeInst be a case class? It seems like we don't want to pattern match and get the FlowDef back out, as it should never be mutated. Tend to think it should not be a case class (and we can add a custom unapply if needed to match the old cases, which does not expose the flowDef).
2. Should we bite the bullet and make an ImmutableFlowDef, which is just exactly cascading's FlowDef with scala Map/Vector/List? Then have functions to copy between? We could have a Monoid of this class to handle the merging.
3. Be on the lookout for any way to make this change smaller, while keeping the TypedPipe immutable. Verify that despite the fact that FlowDefs are mutable, the TypedPipe is still immutable.
4. Can we move the snapshot/save/toIterator/dump methods from the repl directly on to TypedPipe?

TODO:
- [x] audit the Matrix2 code to remove unneeded FlowDefs from the code.
- [x] consider if we can add implicit Mode to `def toPipe` so that we can remove the Mode bound to IterablePipe, EmptyPipe, LiteralValue, EmptyValue. Seems like a possibly harder case.
Good idea. In fact, JobStats is a bit janky, in my mind. I think it should be something like:
```scala
trait JobStats {
  def totals: Map[StatName, Long]
  def steps: Seq[JobStats]
}
```
And then we can define a monoid on them and just add them up. Also, I'm not sure exposing the steps is the right thing to do. Should you really be thinking in terms of steps? How do you reason about that? At the application layer, it seems to me you should use different keys to distinguish, not steps.