Ein Typenmodul exportiert einen Datentyp, und wenn dessen Realisierung nicht im Definitionsmodul angegeben ist (dann heißt dieser Typ ein opaker Typ), tritt ein praktisches Problem auf: um Wertargumente dieses Typs zu übergeben, oder auch um Speicherobjekte für deklarierte Variablen dieses Typs anzulegen, benötigt der Modula-Übersetzer Angaben über den Platzbedarf der durch den Typ beschriebenen Werte, und diese Information ist nicht verfügbar; sie entsteht ja erst bei der Übersetzung des Implementierungsmoduls. Daher gibt es eine Implementierungseinschränkung :DEFINITION MODULE Listen; (* lineare Listen von Elementen des Typs atom *) (* hierher kommt die algebraische Spezifikation *) TYPE liste; PROCEDURE newlist(VAR l: liste): PROCEDURE isempty(l: liste): BOOLEAN; PROCEDURE cons(a: atom; l: liste; VAR r: liste); (* r: = cons(a,l) *) PROCEDURE head(l: liste; VAR a: atom); PROCEDURE tail(l: liste; VAR r: liste); END Listen.
Der Speicherbedarf für Werte eines opaken Typs darf nicht größer sein als der eines Pointerwertes.Diese Einschränkung stört nicht sehr, weil opake Typen tatsächlich meist als Pointertypen realisiert sind, und manche Implementierungen fordern dies sogar.