Алексей Махоткин

домашняя страница

Критика Standard ML — система модулей

Andrew W. Appel, «Критика Standard ML», оглавление

В ML есть система модулей, поддерживающая абстрактные типы данных, сокрытие представления и интерфейсы с проверкой типов. Модули чрезвычайно важны при структурировании больших программных систем.

Многое было написано о преимуществах модулей и абстрактных типов данных. «Классы» в ООП тоже являются модулями, и очень хорошо поддерживают абстрагирование; хороши также «модули» в Modula и Ada. Бесспорно, модули с заданным интерфейсом и сокрытием представления — это одна из важнейших возможностей любого современного языка программирования.

Система модулей ML имеет особенно приятную возможность: она позволяет параметризовать один модуль интерфейсом другого. Ada и Modula также поддерживают «обобщенные» модули, которые можно параметризовать. Однако, ML необычен в том, что параметризованные модули (функторы) можно компилировать, генерируя код, когда настоящие параметры еще не указаны. Те же аргументы «за», что применимы к проверке типов на стадии компиляции, применимы и к проверке функторов при грамматическом разборе, независимо от того, с какими аргументами они будут использоваться.

В языке с параметризованными модулями и абстрактными типами данных необходимо проверять, что данный абстрактный тип всегда ссылается на одно и то же конкретное представление, но при этом не «разглашать» это представление. В Ada и Modula-3 такая проверка возможна, потому что «компиляция» (и проверка типов) тела параметризованного модуля происходит для каждого применения конкретных параметров. В ML можно использовать ключевое слово sharing, чтобы два параметра функтора использовали одно и то же представление совместно используемого абстрактного типа данных.

Например, предположим, что сигнатура (интерфейс) HASH задает модуль, которые сопоставляет строки уникальным токенам. Несомненно, есть различные способы реализовать эту сигнатуру; более того, может существовать несколько объектов с одной и той же реализацией, у каждого из которых своя собственная хэш-таблица. Итак, если модуль Parse с сигнатурой PARSE создает деревья грамматического разбора, содержащие токены, а модуль проверки типов Typecheck (с сигнатурой TYPECHECK) также работает с токенами, то их можно комбинировать в параметризованном модуле Compiler:

functor Compiler( structure P : PARSE
                  structure T : TYPECHECK
                  sharing P.Hash = T.Hash
                ) = . . .

Преимущество параметризации модуля Compile в том, что его можно будет использовать с различными парсерами и различными алгоритмами проверки типов. Конечно же, программа будет бессмысленной, если модуль Parse использует не ту же самую таблицу Hash, что и модуль Typecheck. Более того, если внутреннее представление токенов различается, то программа может даже путать целые с указателями, и т. д. Система модулей ML, возможно, уникальна в том плане, что обеспечивает безопасную комбинацию компилированных параметризованных модулей с абстрактными типами данных.

Comments