Então, eu estou tentando convencer Curry-Howard. (Eu tentei várias vezes, não é gelificante / parece muito abstrato). Para abordar algo concreto, estou trabalhando nos dois tutoriais de Haskell vinculados à wikipedia, especialmente no de Tim Newsham . Também há uma discussão útil quando Newsham postou o tutorial.
(Mas vou ignorar os dataenvoltórios de Newsham e Piponi e falar sobre os tipos subjacentes.) Temos o esquema de axiomas de Hilbert (expresso como combinadores S , K ); nós temos proposições como tipos; implicação como função-seta; e Modus Ponens como aplicação de função:
axK :: p -> q -> p
axK = const
axS :: (p -> q -> r) -> (p -> q) -> p -> r
axS f g x = f x (g x)
modPons = ($); infixl 0 `modPons` -- infix Left, cp ($) is Right
Então eu posso derivar a lei de identidade:
ident = axS `modPons` axK `modPons` axK -- (S K K)
-- ident :: p -> p -- inferred
Ter esses tipos como caracteres simples, apenas correspondendo a proposições, parece um pouco sem imaginação. Posso usar mais do sistema de tipos para realmente construir as proposições? Estou pensando:
data IsNat n = IsNat !n -- [Note **]
data Z = Z
axNatZ :: IsNat Z
axNatZ = IsNat Z
data S n = S !n
axNatS :: IsNat n -> IsNat (S n)
axNatS (IsNat n) = IsNat (S n)
twoIsNat = axNatS `modPons` (axNatS `modPons` axNatZ)
-- ===> IsNat (S (S Z))
[Nota **] Estou usando construtores rigorosos, conforme o tópico da discussão, para evitar a introdução de _ | _ .
Onde:
IsNaté um predicado: fazer uma proposição a partir de um termo.né uma variávelSé uma função, criando um termo a partir de uma variável.Zé uma constante (função niládica).
Então eu pareço ter incorporado a lógica de predicados (de primeira ordem) (?)
Aprecio que meus tipos não são muito higiênicos; Eu poderia facilmente misturar uma typevar-como-proposição com uma typevar-como-termo. Talvez eu deva usar o Kindsistema para segregá-los. OTOH meus axiomas teriam que estar espetacularmente errados para chegar a qualquer conclusão.
Eu não expressei:
- quantificador universal: está implícito nos vars livres;
- quant existencial: de fato, as constantes poderiam atuar como existenciais skememised;
- igualdade de termos: usei repetidos tipos de letra em implicações;
- relações: isso parece funcionar, ou é mancada? ...
data PlusNat n m l = PlusNat !n !m !l
axPlusNatZ :: IsNat m -> PlusNat Z m m
axPlusNatZ (IsNat m) = PlusNat Z m m
axPlusNatS :: PlusNat n m l -> PlusNat (S n) m (S l)
axPlusNatS (PlusNat n m l) = PlusNat (S n) m (S l)
plus123 = axPlusNatS `modPons`
(axPlusNatZ `modPons`
(axNatS `modPons` (axNatS `modPons` axNatZ)) )
-- ===> PlusNat (S Z) (S (S Z)) (S (S (S Z)))
Escrever os axiomas é fácil, cortesia dos Teoremas de Wadler de graça! . Escrever as provas é um trabalho árduo. (Vou largar o modPonse apenas usar o aplicativo de função.)
Isso é realmente alcançar uma lógica? Ou é uma coisa louca? Devo parar antes de causar mais danos ao meu cérebro?
Você precisa de Tipos Dependentes para expressar FOPL em Curry-Howard. Mas eu não pareço estar fazendo isso (?)
IsNaté apenas um tipo, portanto deve ser uma proposição. OK, igualmente IsNat né apenas um tipo, portanto deve ser uma proposição. Devo estar "em minha honra" para não deixar nescapar na terra da proposição / aparecer como argumento para um conectivo lógico (e foi por isso que falei sobre higiene do tipo). Você ficaria mais feliz se eu usasse a codificação da Igreja para Nats? Eu acho que só estou estendendo λ-calc com construtores no nível do tipo, mesmo que Haskell ao nível prazo (?)
n seja uma proposição : está dizendo 'eu sou habitado'. O que não é mais do que qualquer typevar está dizendo sob CH. IsNat nestá dizendo / testemunhando: além disso, o habitante de né de um 'tipo' particular, também conhecido como 'tipo' na lógica. Então eu estou indo além de simplesmente tipado λ-calc (?)
IsNatnão fazer uma proposição a partir de um termo, é fazer uma proposição a partir de uma proposição .