В предыдущем посте я намекнул на то, что понятия «слабо типизированный и сильно типизированный не имеют четких определений и не являются полезными понятиями. Обычно, когда говорят: Язык X слабо типизирован, можно подумать, что слабо типизирован — это характеристика языка X. Это также может привести к мысли, что тип или система типов могут быть каким-то образом слабыми.

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

Случай с Javascript

Рассмотрим оператор + в Javascript. С его помощью мы можем выполнять такие вычисления, как:

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

В приведенном выше коде первые 2 строки обычно считаются безопасными и предсказуемыми (т. е. int+int, float+int), но остальные примеры (3–5) в возрастающем порядке считаются источником проблем. Такая перегрузка арифметических операторов позволяет использовать арифметические выражения, приводящие к «странным значениям», не вызывая ошибок. Рассмотрим следующий оператор Javascript:

execute_sql("SELECT * from table where col=" + (a + b) * 1.5)

Когда a — это строка "10", а b — это число 2, оно оценивается как:

execute_sql("SELECT * from table where col=153")

То есть вместо 18 (если a было числом 10) в результате получаем 153. Предположительно, поскольку эти операции не вызывают ошибку типа при использовании с такими разными типами, а вместо этого возвращают «нормальное» значение, программисты, похоже, думают, что система типов была смягчена или ослаблена. Но поведение — это просто особенность самих операторов. Это операторы, которые были перегружены до такой степени, что рассуждать о них непросто.

На самом деле, мы можем определить тот же оператор Javascript + на таком языке, как Haskell:

В этом примере на Haskell мы создали и перегрузили оператор |+|, чтобы он вел себя примерно так же, как + в Javascript (функция main выполняет те же выражения и выводит те же результаты, что и наш weakly.js Фрагмент Javascript выше). Превратил ли этот код Haskell в язык со слабой типизацией? Или, может быть, он ослабил свою систему типов? Ответ на оба вопроса, естественно, нет.

Изучив код, мы должны сделать вывод, что предположения о неявных приведениях не нужны в качестве объяснения предполагаемого ослабления правил типизации. Скорее достаточно разнообразия типов, четко определенных в сигнатурах операции |+|. Затем мы можем сделать разумный вывод, что оператор + в Javascript может быть смоделирован аналогично перегруженной функции, и сделать вывод, что его тип может быть точно определен в системе звуковых типов.

Кроме того, хотя Haskell предоставляет средство проверки статических типов, неясно, есть ли гарантия того, что все ошибки, возникающие в Javascript из-за этих перегрузок, будут обнаружены средством проверки. Рассмотрим приведенный ниже фрагмент кода как статически типизированный код:

execute_sql("SELECT * from table where col=" + (a + b))

Для оператора +, перегруженного для приема комбинации чисел и строк, приведенный выше код проверяет, являются ли переменные a и b числами или строками. Скорее всего, средство проверки типов сможет определить проблему только тогда, когда, например, a определено как числовой тип и присвоение ему строки не удастся.

Следовательно, мы можем только заключить, что «слабая типизация» не может быть характеристикой ни языка, ни системы типов. Это всего лишь неправильное название, которое просто указывает на наличие функций или операторов со сложной/неинтуитивной сигнатурой/поведением, из-за которых можно легко прийти к неверным предположениям о них [и нет никакой статической проверки типов, которая могла бы помочь]. КЭД