Interfaces in Prolog

Interfaces in Prolog are typically implemented using predicates. We’ll use a similar structure to demonstrate the concept.

% Here's a basic interface for geometric shapes.
:- module(geometry, [area/2, perim/2]).

% For our example we'll implement this interface on
% rect and circle types.
:- module(rect, []).
:- module(circle, []).

% To implement an interface in Prolog, we just need to
% implement all the predicates in the interface. Here we
% implement geometry on rects.
rect:area(rect(Width, Height), Area) :-
    Area is Width * Height.

rect:perim(rect(Width, Height), Perim) :-
    Perim is 2 * Width + 2 * Height.

% The implementation for circles.
circle:area(circle(Radius), Area) :-
    pi(Pi),
    Area is Pi * Radius * Radius.

circle:perim(circle(Radius), Perim) :-
    pi(Pi),
    Perim is 2 * Pi * Radius.

% If a predicate has an interface type, then we can call
% predicates that are in the named interface. Here's a
% generic measure predicate taking advantage of this
% to work on any geometry.
measure(Shape) :-
    writeln(Shape),
    area(Shape, Area),
    writeln(Area),
    perim(Shape, Perim),
    writeln(Perim).

% Main predicate to demonstrate usage
main :-
    R = rect(3, 4),
    C = circle(5),
    % The circle and rect types both
    % implement the geometry interface so we can use
    % instances of these types as arguments to measure.
    measure(R),
    measure(C).

% Helper predicate for pi
pi(3.14159265359).

To run this Prolog program:

?- main.
rect(3, 4)
12
14
circle(5)
78.53981633975
31.4159265359
true.

In Prolog, we use modules to group related predicates, which is similar to how interfaces group related methods in other languages. The geometry module defines the “interface” with area/2 and perim/2 predicates.

The rect and circle modules “implement” this interface by providing their own versions of these predicates. The measure/1 predicate demonstrates how we can use these implementations polymorphically.

Note that Prolog’s approach to polymorphism is quite different from object-oriented languages. It relies on predicate names and arities rather than explicit interface declarations. However, this example demonstrates a way to achieve similar functionality to interfaces in other languages.