Add support for arbitary metadata.

Metadata types can be specified in mdata.go, but are still restricted to compile-time specification.
Each metadata type requires three things:
    - A function for combining two values (e.g., (+) for integers)
    - A identity value under that function (e.g., 0)
    - A unit value (e.g., 1)