Eksperymentuję z systemami czystego typu w sześcianie lambda Barendregta, a konkretnie z najsilniejszym z nich, Rachunkiem Konstrukcji. Ten system ma rodzaje *
i BOX
. Dla przypomnienia, poniżej używam konkretnej składni Morte
narzędzia https://github.com/Gabriel439/Haskell-Morte-Library, która jest zbliżona do klasycznego rachunku lambda.
Widzę, że możemy emulować typy indukcyjne za pomocą pewnego rodzaju kodowania podobnego do Kościoła (znanego również jako izomorfizm Boehm-Berarducci dla algebraicznych typów danych). Dla prostego przykładu używam typu Bool = ∀(t : *) -> t -> t -> t
z konstruktorami True = λ(t : *) -> λ(x : t) -> λ(y : t) -> x
i False = λ(t : *) -> λ(x : t) -> λ(y : t) -> y
.
Widzę, że typ funkcji na poziomie terminu Bool -> T
jest izomorficzny w stosunku do par typu Product T T
o klasycznej Product = λ(A : *) -> λ(B : *) -> ∀(t : *) -> (A -> B -> t) -> t
parametryczności modularnej za pomocą funkcji, if : Bool -> λ(t : *) -> t -> t -> t
która w rzeczywistości jest identyczna.
Wszystkie poniższe pytania dotyczą reprezentacji typów zależnych Bool -> *
.
Mogę podzielić
D : Bool -> *
na paręD True
iD False
. Czy istnieje kanoniczny sposób naD
ponowne utworzenie ? Chcę odtworzyć izomoszmizmBool -> T = Product T T
przez analog funkcjiif
na poziomie typu, ale nie mogę napisać tej funkcji tak prostej jak oryginał,if
ponieważ nie możemy przekazywać rodzajów w argumentach takich jak typy.Używam rodzaju indukcyjnego z dwoma konstruktorami do rozwiązania pytania (1). Opis wysokiego poziomu (w stylu Agda) to następujący typ (używany zamiast poziomu
if
)data BoolDep (T : *) (F : *) : Bool -> * where DepTrue : T -> BoolDep T F True DepFalse : F -> BoolDep T F False
z następującym kodowaniem w PTS / CoC:
λ(T : *) -> λ(F : *) -> λ(bool : Bool ) -> ∀(P : Bool -> *) -> ∀(DepTrue : T -> P True ) -> ∀(DepFalse : F -> P False ) -> P bool
Czy moje kodowanie powyżej jest prawidłowe?
Mogę zapisać konstruktory dla
BoolDep
takiego kodu dlaDepTrue : ∀(T : *) -> ∀(F : *) -> T -> BoolDep T F True
:λ(T : *) -> λ(F : *) -> λ(arg : T ) -> λ(P : Bool -> *) -> λ(DepTrue : T -> P True ) -> λ(DepFalse : F -> P False ) -> DepTrue arg
ale nie mogę zapisać funkcji odwrotnej (ani żadnej funkcji w kierunku odwrotnym). Czy to możliwe? Czy powinienem użyć innej reprezentacji BoolDep
do wytworzenia izomorfizmu BoolDep T F True = T
?