Есть два соглашения, которые я нашел в расширении Coq SSReflect, которые кажутся особенно полезными, но которые я не видел широко принятыми на более новых языках с зависимым от языка (Lean, Agda, Idris).
Во-первых, где возможные предикаты выражаются как функции логического возврата, а не индуктивно определенные типы данных. Это придает разрешимость по умолчанию, открывает больше возможностей для доказательства путем вычислений и улучшает проверку производительности, избегая необходимости в том, чтобы механизм проверки соответствия выполнял большие условия доказательства. Основным недостатком, который я вижу, является необходимость использования рефлексивных лемм для управления этими булевыми предикатами при доказательстве.
Во-вторых, типы данных с инвариантами определяются как зависимые записи, содержащие простой тип данных плюс доказательство инварианта. Например, последовательности фиксированной длины определены в SSR, например:
Structure tuple_of : Type := Tuple {tval :> seq T; _ : size tval == n}.
seq
и доказательство того, что длина этой последовательности является определенным значением. Это противоречит тому, как, например, Idris определяет этот тип:
data Vect : (len : Nat) -> (elem : Type) -> Type
Зависимая типизированная структура данных, в которой инвариант является частью его типа. Одно из преимуществ подхода SSReflect заключается в том, что он позволяет повторно использовать, так что, например, многие функции, определенные для seq
и доказательства о них, все еще могут использоваться с tuple
(работая в базовом seq
), тогда как с помощью функций подхода Idris, таких как reverse
, append
и т.п. необходимо переписать для Vect
. Lean на самом деле имеет эквивалент стиля SSReflect в своей стандартной библиотеке, vector
, но также имеет array
стиля Idris, который, похоже, имеет оптимизированную реализацию во время выполнения.
Одна книга, ориентированная на SSRelect, даже утверждает, что подход Vect n A
style является антипаттерном:
Общим анти-шаблоном в языках с зависимой типизацией и Coq, в частности, является кодирование таких алгебраических свойств в определения самих типов данных и самих функций (канонический пример такого подхода - индексы с индексированием по длине). Хотя этот подход выглядит привлекательным, поскольку он демонстрирует силу зависимых типов для захвата определенных свойств типов данных и функций на них, он по своей сути не масштабируется, так как всегда будет другое интересное свойство, которое не было предусмотрено дизайнером типа/функции, поэтому в любом случае он должен быть закодирован как внешний факт. Вот почему мы защищаем подход, в котором типы данных и функции определяются как близкие к тому, как они будут определены программистом, насколько это возможно, и все необходимые их свойства доказаны отдельно.
Поэтому мой вопрос заключается в том, почему эти подходы не были более широко приняты. Есть ли недостатки, которые у меня отсутствуют, или, может быть, их преимущества менее значительны в языках с лучшей поддержкой зависимого соответствия шаблонов, чем Coq?