A maioria das pessoas evita fornecer descrições precisas sobre o que é uma categoria sintática, porque se você fizer isso corretamente com todos os detalhes, a proporção de insights sobre a sofisticação matemática necessária acaba sendo muito, muito baixa. O livro de John Reynolds, Theories of Programming Languages, tem uma das explicações mais abrangentes em seu capítulo 1, assim como o Fundamentos Práticos de Linguagens de Programação de Robert Harper .
A intuição que você deve ter é que uma categoria sintática é o conjunto de árvores geradas por uma gramática livre de contexto. Dada essa definição para um conjunto de árvores, é possível definir funções nesse conjunto usando recursão estrutural e provar propriedades sobre elas usando indução estrutural : ou seja, analisando casos de todas as maneiras diferentes pelas quais uma árvore pode ser construída.
Por exemplo, suponha que tenhamos um idioma de operações aritméticas fornecido pela seguinte gramática:
e ::= zero | succ(e)| add(e, e)
Em seguida, podemos definir uma função de interpretação eval
que aceita um termo e fornece um número inteiro, por casos, das maneiras pelas quais podemos construir um termo:
eval : Expr -> Int
eval zero = 0
eval succ(e) = 1 + eval e
eval add(e, e') = eval e + eval e'*
Observe que definimos completamente essa função fornecendo uma cláusula para cada maneira possível de gerar uma expressão a partir da gramática. O fato de que essa é uma definição completa de uma função é chamado de princípio da recursão estrutural .
Também podemos provar propriedades sobre essa função usando indução estrutural - fazendo uma análise indutiva para cada caso. Por exemplo, podemos provar que, para cada e
, eval e ≥ 0
.
Proof. By structural induction on e.
- Case e = zero:
By the definition of eval, eval zero = 0.
We know 0 ≥ 0 by reflexivity of ≥.
- Case e = succ(e'):
By induction, we know that eval e' ≥ 0
So we also know that 1 + eval e' ≥ eval e'.
By transitivity, 1 + eval e' ≥ 0.
But eval succ(e') = 1 + eval e'.
So eval succ(e') ≥ 0.
- Case e = add(e', e'').
By induction, we know that eval e' ≥ 0.
By induction, we know that eval e'' ≥ 0.
By properties of addition, we know that eval e' + eval e'' ≥ 0.
By the definition of eval, eval add(e',e'') = eval e' + eval e''.
So eval add(e',e'') ≥ 0.
O fato de considerar apenas os casos de como as expressões podem ser formadas constitui uma prova é chamado de princípio da indução estrutural .
Agora, é possível definir funções por recursão estrutural e provar propriedades por indução estrutural para qualquer gramática. No entanto, provar isso rigorosamente requer uma certa quantidade de teoria das categorias; você precisa formalizar categorias sintáticas como álgebras iniciais de uma determinada classe de functores e, em seguida, provar que essas álgebras iniciais sempre existem para essa classe.
São ferramentas realmente pesadas para provar um resultado tão "óbvio" e, portanto, recomendo apenas confiar na sua intuição sobre como as definições estruturais funcionam e, em seguida, apenas se preocupar com a semântica detalhada se você decidir se tornar um lógico profissional.