Haskell Lambda Alpha等价

时间:2017-12-07 22:32:47

标签: haskell lambda-calculus

我正在尝试在Haskell中为lambda写下一个alpha等价函数。

data Expr = App Expr Expr | Lam Int Expr | Var Int deriving (Show,Eq)

我已经阅读了一些在线资源,但我无法将它们转换为代码。 谢谢

1 个答案:

答案 0 :(得分:1)

因此,如果您可以通过重命名变量将一个表达式转换为另一个表达式,则两个表达式是等效的那我们怎么能抓住这个呢?主要有两种方式:

  1. 跟踪两个表达式中哪些变量名称必须相互对应。
  2. (显式或隐式)转换为一种形式,而不是变量名称,使用封闭范围的编号。
  3. 我们去找第一个

    -- helper functions for association lists
    type Alist a = [(a,a)]
    assoc, rassoc :: Eq a => a -> Alist a -> a
    assoc x ((a,b):ps) = if x == a then b else assoc x ps
    rassoc x = assoc x . map (\(a,b) -> (b,a))
    acons a b l = (a,b):l
    
    (=*=) :: Expr -> Expr -> Bool
    a =*= b = eq [] a b where
      eq l (Lam n x) (Lam m y) = eq (acons n m l) x y
      eq l (Var n) (Var m) = assoc n l == m && n == rassoc m l
      eq l (App f u) (App g v) = eq l f g && eq l u v
      eq l _ _ = False
    

    这里唯一真正的微妙之处在于比较变量。要检查xy是否等同于alpha,我们需要检查x的绑定是否与y的绑定以及y的绑定相对应到x的绑定。否则,我们可能会说\x.\y.x等同于\y.\y.y

    值得注意的是,格式错误的表达式会导致匹配失败。

    以下是如何隐式执行第二个选项:

    varN :: Eq a => a -> [a] -> Int
    varN a xs = v 0 xs where
      v n (x:xs) = if a == x then n else v (n+1) xs
    
    a =*= b = eq [] [] a b in where
      eq k l (Lam n x) (Lam m y) = eq (n:k) (m:l) x y
      eq k l (Var n) (Var m) = varN n k == varN m l
      eq k l (App f u) (App g v) = eq k l f g && eq k l u v
      eq k l _ _ = False
    

    希望你能看到这些是等价的