Это зависит от того, будет ли предикат проверяться статически или динамически. В любом случае ответ - да, но получающиеся системы выглядят по-разному.
На статическом конце: исследователи PL предложили понятие типа уточнения , который состоит из базового типа вместе с предикатом: http://en.wikipedia.org/wiki/Program_refinement. Я считаю, что идея типов уточнения что предикаты проверяются во время компиляции, а это значит, что вы должны ограничить язык предикатов чем-то поддающимся обработке.
Также возможно выразить ограничения, используя зависимые типы , которые являются типами, параметризованными значениями времени выполнения (в отличие от полиморфных типов, которые параметризованы другими типами).
Существуют и другие приемы, которые вы можете использовать с такими мощными системами типов, как Haskell, но IIUC вам придется изменить height
с int
на нечто, о структуре которого может рассуждать средство проверки типов.
На динамическом конце: в SQL есть нечто, называемое domains , как в CREATE DOMAIN
: http://developer.postgresql.org/pgdocs/postgres/sql-createdomain.html (простой пример приведен в нижней части страницы), которое снова состоит из базовый тип и ограничение. Ограничение домена проверяется динамически всякий раз, когда создается значение этого домена. В общем случае вы можете решить эту проблему, создав новый абстрактный тип данных и выполняя проверку всякий раз, когда вы создаете новое значение абстрактного типа. Если ваш язык позволяет вам определять автоматическое приведение от и к вашему новому типу, то вы можете использовать их для реализации SQL-подобных доменов; если нет, то вместо этого вы просто используете простые старые абстрактные типы данных.
Кроме того, существуют контракты, которые не рассматриваются как типы сами по себе, но могут использоваться некоторыми из тех же способов, таких как ограничение аргументов и результатов функций / методов. Простые контракты включают в себя предикаты (например, «принимает объект Person с высотой> 140»), но контракты также могут быть более высокого порядка (например, «принимает объект Person, метод makeSmallTalk () которого никогда не возвращает ноль»). Контракты более высокого порядка не могут быть проверены немедленно, поэтому они обычно включают создание какого-либо прокси. Проверка контракта не создает новый тип значения или не помечает существующие значения, поэтому динамическая проверка будет повторяться при каждом выполнении контракта. Следовательно, программисты часто размещают контракты вдоль границ модулей, чтобы минимизировать избыточные проверки.