Estou experimentando sistemas de tipo puro no cubo lambda de Barendregt, especificamente com o mais poderoso, o Cálculo de Construções. Este sistema tem tipos *
e BOX
. Apenas para constar, abaixo, estou usando a sintaxe concreta da Morte
ferramenta https://github.com/Gabriel439/Haskell-Morte-Library, que fica próxima ao cálculo lambda clássico.
Vejo que podemos emular tipos indutivos por algum tipo de codificação semelhante à Igreja (também conhecido como isomorfismo de Boehm-Berarducci para tipos de dados algébricos). Para um exemplo simples, eu uso type Bool = ∀(t : *) -> t -> t -> t
com os construtores True = λ(t : *) -> λ(x : t) -> λ(y : t) -> x
e False = λ(t : *) -> λ(x : t) -> λ(y : t) -> y
.
Vejo que o tipo de funções de nível de termo Bool -> T
é isomórfico para pares de tipo Product T T
com Product = λ(A : *) -> λ(B : *) -> ∀(t : *) -> (A -> B -> t) -> t
parametricidade clássica de módulo por meio de função if : Bool -> λ(t : *) -> t -> t -> t
que é de fato identidade.
Todas as perguntas abaixo serão sobre representações de tipos dependentes Bool -> *
.
Eu posso dividir
D : Bool -> *
em par deD True
eD False
. Existe a maneira canônica de criarD
novamente? Quero reproduzir o isomosfismoBool -> T = Product T T
por um análogo de funçãoif
no nível de tipo, mas não posso escrever essa função tão simples quanto o original,if
porque não podemos passar tipos em argumentos como tipos.Eu uso um tipo de tipo indutivo com dois construtores para resolver a questão (1). A descrição de alto nível (estilo Agda) é o seguinte tipo (usado em vez do nível de tipo
if
)data BoolDep (T : *) (F : *) : Bool -> * where DepTrue : T -> BoolDep T F True DepFalse : F -> BoolDep T F False
com a seguinte codificação em PTS / CoC:
λ(T : *) -> λ(F : *) -> λ(bool : Bool ) -> ∀(P : Bool -> *) -> ∀(DepTrue : T -> P True ) -> ∀(DepFalse : F -> P False ) -> P bool
Minha codificação acima está correta?
Eu posso escrever os construtores
BoolDep
como este código paraDepTrue : ∀(T : *) -> ∀(F : *) -> T -> BoolDep T F True
:λ(T : *) -> λ(F : *) -> λ(arg : T ) -> λ(P : Bool -> *) -> λ(DepTrue : T -> P True ) -> λ(DepFalse : F -> P False ) -> DepTrue arg
mas não posso escrever a função inversa (ou qualquer função na direção inversa). É possível? Ou devo usar outra representação para BoolDep
produzir um isomorfismo BoolDep T F True = T
?