more efficient and simple serialization, using
function combinators instead of a single GADT