Reputation: 1481
In this answer, the suggested way of "attaching" meta information to types was using a record:
type _foo = ...
and foo = {n:_foo; m:meta}
but what if I have multiple types I'd like to wrap with meta information? Apparently all field names in record types must have different names, and writing:
type _foo = ...
and foo = {n:_foo; m:meta}
...
type _fooX = ...
and fooX = {nX:_fooX; mX:meta}
seems redundant :/. Classes are the only way to solve this? I'd like to avoid dealing with classes, if possible.
Upvotes: 3
Views: 282
Reputation: 31459
Jeffrey's solution is correct and scales perfectly to recursive types.
type location
type 'a loc = { a : 'a; loc : location }
type exp = Int of int | Add of exp loc * exp loc
It is still possible to use the previous two-time definition of your type, as follows:
type exp_data = Int of int | Add of exp * exp
and exp = exp_data loc
Finally, a slightly different style is to use "open recursion", that is to define only an "derecursified type" open_exp
with free parameters instead of recursive occurences. You can then get the recursive type back by taking the fixpoint; you can take different fixpoint, one with no additional information, and one with location interleaved for example. This is a generic construction to insert information at recursion sites, and its term-level counterpart allows for weaving different things in a recursive function (memoization, profiling, debug, etc.).
type 'e open_exp = Int | Add of 'e * 'e
type simple_exp = Simple of simple_exp open_exp
type located_exp = Loc of located_exp loc open_exp
Upvotes: 3
Reputation: 66803
You can use parameterized type, perhaps.
type 'a wrapped = { base: 'a; extra: meta }
Upvotes: 5