やりたいことを行うにはいくつかの方法があります。それらの1つは、異なる構文表現を使用することです。α-同等の用語は実際には等しいです。このような表現は、名前のない、またはローカルで名前のない構文という名前で行われます。人気のあるものは、de Bruijnインデックスを使用しています。この種のことを実装するための電撃的な導入については、私のブログの投稿「依存型理論を実装する方法I、II、III 」を参照してください(パートIIIでde Bruijnインデックスが説明されています)。
あなたがあなたの表現を主張するならば、それでも私達は次のようにド・ブルイン指標を密かに使用するかもしれません。比較中にサブターム内を下降するとき、これまでに遭遇したバインドされた変数のペアのリストを保持します。たとえば、Forall x1 e1
and Forall x2 e2
を比較する場合、ペア(x1, x2)
をリストに追加し、再帰的にe1
andを比較しe2
ます。変数x
とを比較するように求められたらy
、リストを検索します。どちらも同じスポットに表示される必要があります(同じ数量詞によってバインドされていました)か、どちらも表示されておらず、等しい(どちらも自由であり、等しい)かのいずれかです。
私はHaskellに精通していませんが、次のようなものが得られます。
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