Advertisement
Guest User

Untitled

a guest
Dec 13th, 2019
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Data.List (union, (\\))
  2. import Data.Maybe
  3. type Symb = String
  4. infixl 2 :@
  5. infix 1 `alphaEq`
  6.  
  7. data Expr = Var Symb
  8.           | Expr :@ Expr
  9.           | Lam Symb Expr
  10.           deriving (Eq, Read, Show)
  11.  
  12. subst :: Symb -> Expr -> Expr -> Expr
  13. subst v n m = sub m where
  14.   sub e@(Var i)
  15.     | v == i    = n
  16.     | otherwise = e
  17.   sub (f :@ x) = (sub f) :@ (sub x)
  18.   sub (Lam i e)
  19.     | v == i          = Lam i  e
  20.     | i `notElem` fvn = Lam i  (sub e)
  21.     | otherwise       = Lam i' (sub e')
  22.     where
  23.       fvn  = freeVars n
  24.       i' = freshVarName i (fvn `union` freeVars e)
  25.      e' = substVar i i' e  
  26.  
  27. freeVars :: Expr -> [Symb]
  28. freeVars (Var s)   = [s]
  29. freeVars (f :@ a) = freeVars f `union` freeVars a
  30. freeVars (Lam i e) = freeVars e \\ [i]  
  31.  
  32. substVar :: Symb -> Symb -> Expr -> Expr
  33. substVar s s' e = subst s (Var s') e
  34.  
  35. freshVarName :: Symb -> [Symb] -> Symb
  36. freshVarName j js
  37.  | j `elem` js = freshVarName (j ++ "'") js
  38.  | otherwise   = j
  39.  
  40. alphaEq :: Expr -> Expr -> Bool
  41. alphaEq (Var v)   (Var v')    = v == v'
  42. alphaEq (f :@ x)  (f' :@ x')  = alphaEq f f' && alphaEq x x'
  43. alphaEq (Lam s e) (Lam s' e')
  44.  | s == s'                   = e `alphaEq` e'
  45.  | otherwise                 =  substVar s fv e `alphaEq` substVar s' fv e'
  46.  where fv = freshVarName s (freeVars e `union` freeVars e')
  47. alphaEq _         _           = False
  48.  
  49. reduceOnce :: Expr -> Maybe Expr
  50. reduceOnce ((Lam v e) :@ x) = Just $ subst v x e
  51. reduceOnce (f :@ x) | m /= Nothing = Just $ fromJust m :@ x
  52.                    | y /= Nothing = Just $ f :@ (fromJust y)
  53.                    | otherwise = Nothing
  54.                        where
  55.                            m = reduceOnce f
  56.                            y = reduceOnce x
  57. reduceOnce (Lam v e) = if (f /= Nothing) then Just $ Lam v (fromJust f) else Nothing
  58.                           where
  59.                               f = reduceOnce e
  60. reduceOnce _ = Nothing
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement