Почему C++/Java/C# слабые языки

первая часть

В Java 8 так и не появились функции первого класса (функции как типы), однако поддерживаются объекты первого класса (в частности, интерфейсы). Для демонстрации уязвимости системы типов Java воспользуемся примером, предложенным Tony Morris-ом, одним из разработчиков IBM WebSphere и IBM JDK:

interface F<X, Y> {
  Y f(X x);
}

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

interface Monad<A> {
  <B> Monad<B> bind(Monad<A> ma, F<A, Monad<B>> f);
}

Однако это лишь в теории. На практике возникает большая проблема с имплементацией такого интерфейса. Давайте начнём с классической монады MayBe:

final class Maybe<A> implements Monad<A> {
  Maybe<A> bind(final Maybe<A> ma, final F<A, Maybe<B>> f) {
   // ???
  }
}

Увы, но хоть Java и поддерживает коварианты возвращаемых типов, что позволило нам корректно записать интерфейс Monad, однако в ней нету типов высших порядков, поэтому аргумент «final F<A, Maybe<B>> f» будет назван компилятором ошибочным!

Вот это один из грубейших багов в системе типов Java.

Ну хорошо, попробуем прибегнуть к кастингу типов — традиционной кривейшей приляпке, с помощью которой обычно пытаются компенсировать уязвимость и слабость существующей системы типов.

final class Maybe<A> implements Monad<A> {
    public <B> Maybe<B> bind(final Monad<A> ma, final F<A, Monad<B>> f) {
        if (ma instanceof Maybe) {
            // return ... ;
        }
        return null;
    }
}

Такая схема сработает, однако очевидные её недостатки — необходимость явного кастинга, что никак нельзя назвать удовлетворительным решением, ну и множество побочных эффектов (например, что делать, если тип монады — другой? явно, вручную прописывать все варианты обработки в каждом методе?). На самом деле, отсутствие типов высших порядков в системе типов конкретного языка практически всегда влечёт за собой множество антагонистических проблем с потенциально разрушительными последствиями.

А наш пример — это показатель того, что судить о языках с «сильной типизацией» и делать какие-то обобщающие выводы совершенно неверно, если в качестве оной выбирается система типов языка с, на самом деле, явно слабой типизацией, наподобие С++, C#, Java, …

Тут есть такая опасность, что если уж оказывается, что у этих мэйнстримовских языков система типов слабая, то не лучше ли двинуть в сторону языков с динамической типизацией, наподобие Python?

Нет! Правильное решение — всегда как можно более сильная система типов!

Итак, резюме:

— Для схемы сильной типизации фундаментально необходимы типы высших порядков;

— Мэйнстримовские языки, претендующие на звание сильной типизации, (Java / C ++ / C#, …) не поддерживают типы высших порядков, поэтому на самом деле не поддерживают и сильную типизацию; их типизацию правильно считать weak/слабой;

— Монадическое связывание — довольно простая и очень распространенная концепция программирования, которую разработчики применяют повсеместно, но не всегда об этом догадываются;

— Монадическое связывание не может быть прозрачно выражено в мэйнстримовских системах со слабой типизацией;

— Динамическая типизация — отнюдь не единственное и точно не самое сильное решение проблем систем со слабой типизацией.

Полезно также немного обобщить эти выводы и отдельно подумать:

— Если мы попытаемся моделировать концепцию, которая уже будет не столь тривиальной, как монадическое связывание? Будет ли сложность вычисления зависеть линейно от сложности такой концепции?

— Какие ещё важные концепции поддерживаются системами с сильной типизацией, но отсутствуют в мэйнстримовских системах, только на словах претендующих на «strong type system»?

— Хорошо бы эти важные концепции также явно выразить в виде примеров «почему это невозможно» в C++ или Java, кроме уже рассмотренных типов высших порядков.

Что касается любых рассуждений о силе системы типов, её можно вести лишь в дискретном пространстве «очень сильная, очень выразительная и очень типобезопасная система VS динамическая типизация». Все эксперименты с типами с помощью промежуточных систем с псевдосильной, а на самом деле слабой и уязвимой типизацией, никакой пользы теме сильной типизации принести не могут в принципе, а будут только вредить обучению программированию.

Поделиться статьей ...Share on Facebook0Share on Google+0Tweet about this on TwitterShare on LinkedIn0Share on VKPrint this page

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *