Я экспериментирую с системами чистого типа в лямбда-кубе Барендрегта, особенно с наиболее мощным, исчислением конструкций. Эта система имеет сорта *
и BOX
. Для справки ниже я использую конкретный синтаксис Morte
инструмента https://github.com/Gabriel439/Haskell-Morte-Library, который близок к классическому лямбда-исчислению.
Я вижу, что мы можем эмулировать индуктивные типы с помощью некоторого церковно-подобного кодирования (так называемый изоморфизм Бёма-Берардуччи для алгебраических типов данных). Для простого примера я использую тип Bool = ∀(t : *) -> t -> t -> t
с конструкторами True = λ(t : *) -> λ(x : t) -> λ(y : t) -> x
и False = λ(t : *) -> λ(x : t) -> λ(y : t) -> y
.
Я вижу, что тип функций уровня членов Bool -> T
изоморфен парам типа Product T T
с классической Product = λ(A : *) -> λ(B : *) -> ∀(t : *) -> (A -> B -> t) -> t
по модулю параметричности посредством функции, if : Bool -> λ(t : *) -> t -> t -> t
которая фактически тождественна.
Все вопросы ниже будут о представлениях зависимых типов Bool -> *
.
Я могу разделить
D : Bool -> *
на паруD True
иD False
. Есть ли канонический способ создатьD
заново? Я хочу воспроизвести изоморфизмBool -> T = Product T T
с помощью аналога функцииif
на уровне типа, но я не могу написать эту функцию так же просто, как оригинал,if
потому что мы не можем передавать виды в аргументах, таких как типы.Я использую своего рода индуктивный тип с двумя конструкторами для решения вопроса (1). Описание высокого уровня (стиль Agda) - это следующий тип (используется вместо уровня типа
if
)data BoolDep (T : *) (F : *) : Bool -> * where DepTrue : T -> BoolDep T F True DepFalse : F -> BoolDep T F False
со следующей кодировкой в PTS / CoC:
λ(T : *) -> λ(F : *) -> λ(bool : Bool ) -> ∀(P : Bool -> *) -> ∀(DepTrue : T -> P True ) -> ∀(DepFalse : F -> P False ) -> P bool
Правильна ли моя кодировка выше?
Я могу записать конструкторы для
BoolDep
этого кода дляDepTrue : ∀(T : *) -> ∀(F : *) -> T -> BoolDep T F True
:λ(T : *) -> λ(F : *) -> λ(arg : T ) -> λ(P : Bool -> *) -> λ(DepTrue : T -> P True ) -> λ(DepFalse : F -> P False ) -> DepTrue arg
но я не могу записать обратную функцию (или любую функцию в обратном направлении). Является ли это возможным? Или я должен использовать другое представление для BoolDep
создания изоморфизма BoolDep T F True = T
?
источник
Ответы:
Вы не можете сделать это, используя традиционную церковную кодировку для
Bool
:... потому что вы не можете написать (полезную) функцию типа:
Причина , почему, как вы отметили, что вы не можете передать в
*
качестве первого аргумента#Bool
, который в свою очередь означает , чтоTrue
иFalse
аргументы не могут быть типы.Есть как минимум три способа решить эту проблему:
Используйте исчисление индуктивных конструкций. Тогда вы можете обобщить тип
#Bool
:... и затем вы создадите экземпляр
n
для1
, что означает, что вы можете передать в*₀
качестве второго аргумента, который будет проверять тип, потому что:... так что вы можете использовать
#Bool
для выбора между двумя типами.Добавьте еще один сорт:
Тогда вы бы определили отдельный
#Bool₂
тип следующим образом:По сути, это частный случай исчисления индуктивных конструкций, но он производит менее многократно используемый код, поскольку теперь мы должны поддерживать два отдельных определения
#Bool
, по одному для каждого вида, который мы хотим поддерживать.Кодировать
#Bool₂
непосредственно в исчислении конструкций как:Если цель состоит в том, чтобы использовать это непосредственно в неизмененном виде,
morte
то будет работать только подход № 3.источник
#Bool₁
в#Bool₂