SML# Document Version 3.7.1
8 SML# feature: record polymorphism

8.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 Chapter12, 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 = fn : [’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.