Interfaces in Standard ML

Standard ML (SML) doesn’t have a direct equivalent to interfaces, but we can use modules and signatures to achieve similar functionality. Here’s how we can implement the geometry example in SML:

(* Basic signature for geometric shapes *)
signature GEOMETRY = sig
    val area : unit -> real
    val perim : unit -> real
end

(* Implementation for rectangles *)
structure Rect :> GEOMETRY = struct
    val width = ref 0.0
    val height = ref 0.0
    
    fun area () = !width * !height
    fun perim () = 2.0 * !width + 2.0 * !height
    
    fun init (w: real, h: real) =
        (width := w; height := h)
end

(* Implementation for circles *)
structure Circle :> GEOMETRY = struct
    val radius = ref 0.0
    
    fun area () = Math.pi * !radius * !radius
    fun perim () = 2.0 * Math.pi * !radius
    
    fun init (r: real) = radius := r
end

(* Generic measure function *)
fun measure (geom: GEOMETRY) =
    let
        val area = geom.area()
        val perim = geom.perim()
    in
        (print ("Area: " ^ Real.toString area ^ "\n");
         print ("Perimeter: " ^ Real.toString perim ^ "\n"))
    end

(* Main function *)
fun main () =
    (Rect.init(3.0, 4.0);
     Circle.init(5.0);
     print "Rectangle:\n";
     measure Rect;
     print "\nCircle:\n";
     measure Circle)

(* Run the main function *)
val _ = main()

In this SML implementation:

  1. We define a GEOMETRY signature that specifies the interface for geometric shapes. It includes area and perim functions.

  2. We create Rect and Circle structures that implement the GEOMETRY signature. Each structure has its own internal state (width and height for rectangles, radius for circles) and implements the required functions.

  3. The measure function takes a GEOMETRY module and calls its area and perim functions, printing the results.

  4. In the main function, we initialize a rectangle and a circle, then call measure on each of them.

To run this program:

$ sml geometry.sml
Rectangle:
Area: 12.0
Perimeter: 14.0

Circle:
Area: 78.53981633974483
Perimeter: 31.41592653589793

This implementation showcases how SML’s module system can be used to create abstractions similar to interfaces in other languages. The GEOMETRY signature defines a contract that both Rect and Circle structures adhere to, allowing us to write generic functions like measure that can work with any structure implementing the GEOMETRY signature.