Sto sperimentando sistemi di tipo puro nel cubo lambda di Barendregt, in particolare con il più potente, il Calculus of Constructions. Questo sistema ha specie *
e BOX
. Per la cronaca, di seguito sto usando la sintassi concreta dello Morte
strumento https://github.com/Gabriel439/Haskell-Morte-Library che è vicino al classico calcolo lambda.
Vedo che possiamo emulare tipi induttivi mediante una sorta di codifica simile alla Chiesa (alias isomorfismo di Boehm-Berarducci per tipi di dati algebrici). Per un semplice esempio uso tipo Bool = ∀(t : *) -> t -> t -> t
con i costruttori True = λ(t : *) -> λ(x : t) -> λ(y : t) -> x
e False = λ(t : *) -> λ(x : t) -> λ(y : t) -> y
.
Vedo che il tipo di funzioni a livello di termine Bool -> T
è isomorfo per coppie di tipi Product T T
con Product = λ(A : *) -> λ(B : *) -> ∀(t : *) -> (A -> B -> t) -> t
parametricità modulo classica per mezzo di una funzione if : Bool -> λ(t : *) -> t -> t -> t
che è in realtà identità.
Tutte le domande che seguono saranno sulle rappresentazioni di tipi dipendenti Bool -> *
.
Posso dividere
D : Bool -> *
in coppia diD True
eD False
. Esiste il modo canonico per creare diD
nuovo? Voglio riprodurre l'isomosfismoBool -> T = Product T T
da un analogo della funzioneif
a livello di tipo, ma non posso scrivere questa funzione tanto semplice quanto originaleif
perché non possiamo passare i tipi in argomenti come i tipi.Uso una specie di tipo induttivo con due costruttori per risolvere la domanda (1). La descrizione di alto livello (stile Agda) è il seguente tipo (utilizzato anziché a livello di tipo
if
)data BoolDep (T : *) (F : *) : Bool -> * where DepTrue : T -> BoolDep T F True DepFalse : F -> BoolDep T F False
con la seguente codifica in PTS / CoC:
λ(T : *) -> λ(F : *) -> λ(bool : Bool ) -> ∀(P : Bool -> *) -> ∀(DepTrue : T -> P True ) -> ∀(DepFalse : F -> P False ) -> P bool
La mia codifica sopra è corretta?
Posso scrivere i costruttori
BoolDep
come questo codice perDepTrue : ∀(T : *) -> ∀(F : *) -> T -> BoolDep T F True
:λ(T : *) -> λ(F : *) -> λ(arg : T ) -> λ(P : Bool -> *) -> λ(DepTrue : T -> P True ) -> λ(DepFalse : F -> P False ) -> DepTrue arg
ma non riesco a scrivere la funzione inversa (o nessuna funzione nella direzione inversa). È possibile? O dovrei usare un'altra rappresentazione per BoolDep
produrre un isomorfismo BoolDep T F True = T
?