Algorithmus zur Entscheidung der Alpha-Äquivalenz von Begriffen in Sprachen mit Bindungen

7

Ich interessiere mich für die Alpha-Äquivalenzbeziehung in Sprachen mit variablen Bindungen, wie zum Beispiel:

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

Oder der reine Lambda-Kalkül:

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

Ich suche nach einem Algorithmus, mit dem ich feststellen kann, ob zwei Begriffe der Sprache Alpha-äquivalent sind oder nicht. Jede veröffentlichte Referenz ist ebenfalls sehr willkommen. Ich gehe von einer Datendarstellung der Begriffe als rekursiven Standardtyp aus, zum Beispiel in Haskell:

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

Antworten:

9

Es gibt verschiedene Möglichkeiten, um das zu tun, was Sie wollen. Eine davon ist die Verwendung einer anderen Syntaxdarstellung, unter derα-äquivalente Begriffe sind tatsächlich gleich. Solche Darstellungen werden unter der namenlosen oder lokal namenlosen Syntax geführt. Ein beliebter verwendet de Bruijn-Indizes . In meinen Blog-Beiträgen zur Implementierung der abhängigen Typentheorie I , II und III finden Sie eine Einführung in die Implementierung dieser Art von Dingen (in Teil III wurden die De-Bruijn-Indizes erläutert).

Wenn Sie auf Ihrer Darstellung bestehen, können wir die De-Bruijn-Indizes weiterhin wie folgt heimlich verwenden. Während wir während des Vergleichs innerhalb eines Subterms absteigen, führen wir eine Liste von Paaren gebundener Variablen, die bisher angetroffen wurden. Beim Vergleichen von Forall x1 e1und Forall x2 e2fügen wir beispielsweise das Paar (x1, x2)zur Liste hinzu und vergleichen rekursiv e1und e2. Wenn wir aufgefordert werden, Variablen xund zu vergleichen y, durchsuchen wir die Liste: Entweder müssen beide an derselben Stelle erscheinen (sie wurden an denselben Quantifizierer gebunden) oder keiner erscheint und sie sind gleich (sie sind beide frei und sie sind gleich).

Ich bin mit Haskell nicht vertraut, aber Sie würden so etwas bekommen:

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
quelle
Andrej, das funktioniert perfekt, danke!
Sven Williamson