Effectively a complete rewrite based on GADTs; Play nicer with Lwt, etc.

GADTs provide some nicer implementation guarantees without a significant
performance loss vs the previous implementation based on phantom types.
'make bench && ./bench_test.native' shows similar results before and after
this change.

The 'u parameter captures the return value of writes.  This makes it easier
to use IndexMap with write functions which return something other than
unit.