Algoritmo para decidir a equivalência alfa de termos em idiomas com ligações

7

Estou interessado na relação de equivalência alfa em idiomas com ligações variáveis, como:

t := x:y    'x belong to y'
  | bot     'False'
  | t -> t  'implication'
  | Ax.t    'forall x, t'

Ou o cálculo lambda puro:

t := x       'variable'
  | (t t)    'application '
  | Lx.t     'abstraction: \x -> t'

Estou procurando um algoritmo que permita determinar se dois termos da linguagem são equivalentes a alfa ou não. Qualquer referência publicada também é muito bem-vinda. Estou assumindo uma representação de dados dos termos como um tipo recursivo padrão, por exemplo, em Haskell:

newtype Var = Var Int 
data Term = Belong Var Var
          | Bot
          | Imply Term Term
          | Forall Var Term 
Sven Williamson
fonte

Respostas:

9

Existem várias maneiras de fazer o que você deseja. Uma delas é usar uma representação de sintaxe diferente sob a qualαtermos -equivalentes são realmente iguais. Tais representações têm o nome de sintaxe sem nome ou localmente sem nome . Um popular usa índices de Bruijn . Veja minhas postagens no blog Como implementar a teoria dos tipos dependentes I , II e III para uma introdução rápida à implementação desse tipo de coisa (a parte III explicou os índices de Bruijn).

Se você insistir em sua representação, ainda poderemos usar secretamente os índices de Bruijn, como a seguir. À medida que descemos dentro de um subtermo durante a comparação, mantemos uma lista de pares de variáveis ​​ligadas encontradas até o momento. Por exemplo, ao comparar Forall x1 e1e Forall x2 e2, adicionamos o par (x1, x2)à lista e comparamos recursivamente e1e e2. Quando solicitados a comparar variáveis xe y, procuramos na lista: ou elas devem aparecer no mesmo local (estavam vinculadas pelo mesmo quantificador) ou nenhuma aparecer e são iguais (são livres e são iguais).

Eu não sou bem versado em Haskell, mas você teria algo assim:

newtype Var = Var Int deriving Eq

data Term = Belong Var Var
          | Bot
          | Imply Term Term
          | Forall Var Term

equalVar :: [(Var,Var)] -> Var -> Var -> Bool
equalVar [] x y = (x == y)
equalVar ((x,y):bound) z w = (x == z && y == w) || (x /= z && y /= w && equalVar bound z w)

equal' :: [(Var, Var)] -> Term -> Term -> Bool
equal' bound (Belong x1 y1) (Belong x2 y2) = (equalVar bound x1 x2 && equalVar bound y1 y2)
equal' bound Bot Bot = True
equal' bound (Imply u1 v1) (Imply u2 v2) = equal' bound u1 u2 && equal' bound v1 v2
equal' bound (Forall x u) (Forall y v) = equal' ((x,y):bound) u v
equal' _ _ _ = False

equal :: Term -> Term -> Bool
equal e1 e2 = equal' [] e1 e2
Andrej Bauer
fonte
Andrej, isso funciona perfeitamente obrigado!
Sven Williamson