Ch.7 SML# feature: record polymorphism

§ 7.6. Representing objects

Records are the fundamental data structures, and they are the basis for various data manipulation models such as relational databases and object-oriented programming. As explained in Chapter10, SML# seamlessly integrate SQL based on record polymorphism. Object-oriented programming is based on a different computation model than functional programming, and we do not hope to represent it in a functional language. However, generic object manipulation underlying object-oriented programming is naturally represented using record polymorphism.

An object has a statue, receives method selector and invoke the designated method on its state. A class can be regarded as the set of methods that belongs to the class. So we can represent a class structure as a record of methods. Each method is coded as a function that takes a state of an object and update it. For example, consider an object in a pointClass having X coordinate, Y coordinate, Color property. An object state can be represented by a reference to a record of the those values such as {X = 1.1, Y = 2.2}. Then a method can be defined as a function that takes an object state as self and update the state. For example, a method to set a value in the X coordinate can be coded as follows.

# fn self => fn x => self := (!self # {X = x});
val it = _ : ['a#{X: 'b},'b. 'a ref -> 'b -> unit]

This method can be applied to any objects that contain X attributes. A class can be a record consisting of these methods with appropriate names. For example,pointClass can be defined as below.

val pointClass =
{
  getX = fn self => #X (!self),
  setX = fn self => fn x => self := (!self # X = x),
  getY = fn self => #Y (!self),
  setY = fn self => fn x => self := (!self # Y = x),
  getColor = fn self => #Color (!self),
  setColor = fn self => fn x => self := (!self # Color = x)
}

An object receives a message and invoke the corresponding method on itself. In SML#, this is coded below.

local
  val state = ref { X = 0.0, Y = 0.0 }
in
  val myPoint = fn method => method pointClass state
end

We can similarly define an object having Color attribute.

local
  val state = ref { X = 0.0, Y = 0.0, Color = "Red" }
in
  val myColorPoint = fn method => method pointClass state
end

Under these definition, we can write the following code.

# myPoint # setX 1.0;
val it = () : unit
# myPoint # getX;
val it = 1.0 : real
# myColorPoint # getX;
val it = 0.0 : real
# myColorPoint # getColor;
val it = "Red" : string
# myPoint # getColor;
(interactive):15.1-15.12 Error:
  (type inference 007) operator and operand don't agree
  ...

As shown in the last example, the system detect all the type errors statically.