# § 7.7. Polymorphic variants

Records are labeled collection of component values. There is a dual concept of this structure, namely labeled variants. This may not be familiar to many of you, but the essential ingredients are the same as those of records, so in a system where polymorphic records are supported, polymorphic variants can also be represented. For a type theoretical account, see [8]. In this section, we briefly introduce them through simple examples.

Once you understand records as labeled collections of values, you can think of labeled variants as a value attached with a service request label in a context where a labeled collection of services are defined. For a simple example, let us consider a system where we have two point representations, one in Cartesian coordinates and the other in polar coordinates. In this system, each representation is processed differently, so each point data is attached a label indicating its representation. Polymorphic variant is a mechanisms to those data with polymorphic functions. By regarding the data label as a service selector from a given set of services, this system can be represented by polymorphic records. For example, the following show two representations of the same point.

# val myCPoint = fn M => #CPoint M {X=1.0, Y = 1.0};

val myCPoint = fn : ['a#{CPoint: {X: real, Y: real} -> 'b}, 'b. 'a -> 'b]

# val myPPoint = fn M => #PPoint M {r=1.41421356, theta = 45.0 };

val myPPoint = fn : ['a#{PPoint: {r: real, theta: real} -> 'b}, 'b. 'a -> 'b]

A variant data with a tag

val distance =

{

CPoint = fn x,y,... => Real.Math.sqrt (x *x + y* y),

PPoint = fn r, theta,... => r

};

This method suit is invoked by applying an variant object to it.

# myCPoint distance ;

val it = 1.41421356 : real

# myPPoint distance ;

val it = 1.41421356 : real

In this way, various heterogeneous collections can be processed in type safe way.