| 1 | -- |
|---|
| 2 | -- Copyright (C) 2012 Attila Gobi - http://kp.elte.hu/sizechecking |
|---|
| 3 | -- |
|---|
| 4 | |
|---|
| 5 | module Lambda where |
|---|
| 6 | |
|---|
| 7 | {- |
|---|
| 8 | Ez a cikkben megadott lambda kalkulus egy implementacioja + redukcio + peldak. |
|---|
| 9 | |
|---|
| 10 | Hasznalat: lasd Lambda_proof.hs |
|---|
| 11 | |
|---|
| 12 | -} |
|---|
| 13 | import Data.List |
|---|
| 14 | import qualified Data.Set as Set |
|---|
| 15 | import Data.Char |
|---|
| 16 | |
|---|
| 17 | data L = Abs Int L | App L L | Var Int | Num Int | Op L Char L | List L L | AAbs Int Int L |
|---|
| 18 | | Shift L L L | Unsized | Bottom |
|---|
| 19 | deriving (Eq, Ord) |
|---|
| 20 | |
|---|
| 21 | showVar x = if x>28 |
|---|
| 22 | then showVar (x `div` 29) . showChar (chr $ ord 'a' + (x `mod` 29)) |
|---|
| 23 | else showChar $ chr $ ord 'a' + x |
|---|
| 24 | |
|---|
| 25 | getPrec :: Char -> (Int,Int,Int) |
|---|
| 26 | getPrec '+' = (4,4,5) |
|---|
| 27 | getPrec '-' = (4,4,5) |
|---|
| 28 | getPrec '*' = (5,5,6) |
|---|
| 29 | getPrec '/' = (5,5,6) |
|---|
| 30 | getPrec c = error $ "Unknown operator "++[c] |
|---|
| 31 | |
|---|
| 32 | instance Show L where |
|---|
| 33 | showsPrec p (Abs s l) = showParen (p>0) $ showChar 'λ' . showVar s . showChar '.' . shows l |
|---|
| 34 | showsPrec p (AAbs f s l) = showParen (p>0) $ showChar 'Î' . showVar f . showChar ',' . showVar s . showChar '.' . shows l |
|---|
| 35 | showsPrec p (App m n) = showParen (p>6) $ showsPrec 6 m . showChar ' ' . showsPrec 7 n |
|---|
| 36 | showsPrec _ (Var s) = showVar s |
|---|
| 37 | showsPrec _ (Num i) = shows i |
|---|
| 38 | showsPrec p (Op m op n) = showParen (p>prec) $ showsPrec lprec m . showChar op . showsPrec rprec n |
|---|
| 39 | where (prec,lprec,rprec)=getPrec op |
|---|
| 40 | showsPrec p (List s f) = showParen (p>0) $ showString "List " . showsPrec 9 s . showChar ' ' . showsPrec 9 f |
|---|
| 41 | showsPrec p (Shift e1 s e2) = showParen (p>0) $ showString "Shift " .showsPrec 2 e1 . |
|---|
| 42 | showChar ' ' . showsPrec 2 s . showChar ' ' . showsPrec 2 e2 |
|---|
| 43 | showsPrec _ Bottom = showChar 'âŽ' |
|---|
| 44 | showsPrec _ Unsized = showChar 'U' |
|---|
| 45 | |
|---|
| 46 | t3s = Abs 1 $ Abs 0 $ App t (App t (App t x)) |
|---|
| 47 | where t = Var 1 |
|---|
| 48 | x = Var 0 |
|---|
| 49 | |
|---|
| 50 | subs (App x z) var exp = App (subs x var exp) (subs z var exp) |
|---|
| 51 | subs (List s f) var exp = List (subs s var exp) (subs f var exp) |
|---|
| 52 | subs (Shift e1 e2 e3) var exp = Shift (subs e1 var exp) (subs e2 var exp) (subs e3 var exp) |
|---|
| 53 | subs (Op x c z) var exp = Op (subs x var exp) c (subs z var exp) |
|---|
| 54 | subs e@(Var v) var exp | v==var = exp |
|---|
| 55 | | otherwise = e |
|---|
| 56 | subs x@(Abs v e) var exp | v==var = x |
|---|
| 57 | | otherwise = Abs v (subs e var exp) |
|---|
| 58 | subs x@(AAbs s f e) var exp | s==var||f==var = x |
|---|
| 59 | | otherwise = AAbs s f (subs e var exp) |
|---|
| 60 | subs x@(Num _) _ _ = x |
|---|
| 61 | subs x@Bottom _ _ = x |
|---|
| 62 | subs x@Unsized _ _ = x |
|---|
| 63 | |
|---|
| 64 | |
|---|
| 65 | alpha (App x z) from to = App (alpha x from to) (alpha z from to) |
|---|
| 66 | alpha (List x z) from to = List (alpha x from to) (alpha z from to) |
|---|
| 67 | alpha (Op x c z) from to = Op (alpha x from to) c (alpha z from to) |
|---|
| 68 | alpha (Shift x y z) from to = Shift (alpha x from to) (alpha y from to) (alpha z from to) |
|---|
| 69 | alpha e@(Var _) _ _ = e |
|---|
| 70 | alpha e@(Num _) _ _ = e |
|---|
| 71 | alpha e@Bottom _ _ = e |
|---|
| 72 | alpha e@Unsized _ _ = e |
|---|
| 73 | alpha (Abs v e) from to | v==from = Abs to (alpha' e from to) |
|---|
| 74 | | otherwise = Abs v (alpha e from to) |
|---|
| 75 | alpha (AAbs v1 v2 e) from to | v1==from = AAbs to v2 (alpha' e from to) |
|---|
| 76 | | v2==from = AAbs v1 to (alpha' e from to) |
|---|
| 77 | | otherwise = AAbs v1 v2 (alpha e from to) |
|---|
| 78 | |
|---|
| 79 | alpha' (App x z) from to = App (alpha' x from to) (alpha' z from to) |
|---|
| 80 | alpha' (List x z) from to = List (alpha' x from to) (alpha' z from to) |
|---|
| 81 | alpha' (Op x c z) from to = Op (alpha' x from to) c (alpha' z from to) |
|---|
| 82 | alpha' (Shift x y z) from to = Shift (alpha' x from to) (alpha' y from to) (alpha' z from to) |
|---|
| 83 | alpha' e@(Var v) from to | v==from = Var to |
|---|
| 84 | | otherwise = e |
|---|
| 85 | alpha' (Abs v e) from to | v==from = Abs to (alpha' e from to) |
|---|
| 86 | | otherwise = Abs v (alpha' e from to) |
|---|
| 87 | alpha' (AAbs v1 v2 e) from to | v1==from = AAbs to v2 (alpha' e from to) |
|---|
| 88 | | v2==from = AAbs v1 to (alpha' e from to) |
|---|
| 89 | | otherwise = AAbs v1 v2 (alpha' e from to) |
|---|
| 90 | alpha' x@(Num _) _ _ = x |
|---|
| 91 | alpha' x@Bottom _ _ = x |
|---|
| 92 | alpha' x@Unsized _ _ = x |
|---|
| 93 | |
|---|
| 94 | fv (Var x) = Set.singleton x |
|---|
| 95 | fv (App x y) = fv x `Set.union` fv y |
|---|
| 96 | fv (Op x _ y) = fv x `Set.union` fv y |
|---|
| 97 | fv (Abs v e) = v `Set.delete` fv e |
|---|
| 98 | fv (AAbs x y e) = x `Set.delete` ( y `Set.delete` fv e) |
|---|
| 99 | fv (List s e) = fv s `Set.union` fv e |
|---|
| 100 | fv (Num _) = Set.empty |
|---|
| 101 | fv (Shift e1 e2 e3) = fv e1 `Set.union` fv e2 `Set.union` fv e3 |
|---|
| 102 | fv Unsized = Set.empty |
|---|
| 103 | fv Bottom = Set.empty |
|---|
| 104 | |
|---|
| 105 | bv (Var _) = Set.empty |
|---|
| 106 | bv (App x y) = bv x `Set.union` bv y |
|---|
| 107 | bv (Op x _ y) = bv x `Set.union` bv y |
|---|
| 108 | bv (List x y) = bv x `Set.union` bv y |
|---|
| 109 | bv (Abs v e) = v `Set.insert` bv e |
|---|
| 110 | bv (AAbs v1 v2 e) = v1 `Set.insert` (v2 `Set.insert` bv e) |
|---|
| 111 | bv (Shift e1 e2 e3) = bv e1 `Set.union` bv e2 `Set.union` bv e3 |
|---|
| 112 | bv (Num _) = Set.empty |
|---|
| 113 | bv Unsized = Set.empty |
|---|
| 114 | bv Bottom = Set.empty |
|---|
| 115 | |
|---|
| 116 | maxv (Var x) = x |
|---|
| 117 | maxv (Num _) = 0 |
|---|
| 118 | maxv Unsized = 0 |
|---|
| 119 | maxv Bottom = 0 |
|---|
| 120 | maxv (App x y) = maxv x `max` maxv y |
|---|
| 121 | maxv (Op x _ y) = maxv x `max` maxv y |
|---|
| 122 | maxv (Shift x y z) = maxv x `max` maxv y `max` maxv z |
|---|
| 123 | maxv (List x y) = maxv x `max` maxv y |
|---|
| 124 | maxv (Abs v e) = v `max` maxv e |
|---|
| 125 | maxv (AAbs v1 v2 e) = v1 `max` v2 `max` maxv e |
|---|
| 126 | |
|---|
| 127 | rsubs oexp var exp = subs renamed var exp |
|---|
| 128 | where |
|---|
| 129 | dvar = fv exp `Set.intersection` bv oexp |
|---|
| 130 | m = maxv exp `max` maxv oexp |
|---|
| 131 | renames = zip (Set.toList dvar) [m+1..] |
|---|
| 132 | renamed = foldr rename oexp renames |
|---|
| 133 | rename (from,to) _ = alpha oexp from to |
|---|
| 134 | |
|---|
| 135 | |
|---|
| 136 | reduce (App (Abs var exp) z) = return $ rsubs exp var z |
|---|
| 137 | reduce (App (AAbs s f exp) (List s' f')) = return $ rsubs (App (Abs f exp) f') s s' |
|---|
| 138 | reduce (App e f) = case reduce e of |
|---|
| 139 | Just e' -> return $ App e' f |
|---|
| 140 | _ -> reduce f >>= \f' -> return $ App e f' |
|---|
| 141 | reduce (Abs v e) = reduce e >>= \e' -> return $ Abs v e' |
|---|
| 142 | reduce (Var _) = Nothing |
|---|
| 143 | reduce (Num _) = Nothing |
|---|
| 144 | reduce (List e f) = case reduce e of |
|---|
| 145 | Just e' -> return $ List e' f |
|---|
| 146 | _ -> reduce f >>= \f' -> return $ List e f' |
|---|
| 147 | reduce (AAbs v1 v2 e) = reduce e >>= \e' -> return $ AAbs v1 v2 e' |
|---|
| 148 | reduce Unsized = Nothing |
|---|
| 149 | reduce Bottom = Nothing |
|---|
| 150 | reduce (Shift e1 e2 e3) = case reduce e1 of |
|---|
| 151 | Just e' -> return $ Shift e' e2 e3 |
|---|
| 152 | _ -> case reduce e2 of |
|---|
| 153 | Just e' -> return $ Shift e1 e' e3 |
|---|
| 154 | _ -> reduce e3 >>= \e' -> return $ Shift e1 e2 e' |
|---|
| 155 | reduce (Op m c n) = case c of |
|---|
| 156 | '+' | (Num i, Num j) <- (m,n) -> return $ Num $ i+j |
|---|
| 157 | '-' | (Num i, Num j) <- (m,n) -> return $ Num $ i-j |
|---|
| 158 | '*' | (Num i, Num j) <- (m,n) -> return $ Num $ i*j |
|---|
| 159 | '+' | (Num 0) <- m -> reduce n |
|---|
| 160 | '+' | (Num 0) <- n -> reduce m |
|---|
| 161 | '*' | (Num 0) <- m -> return $ Num 0 |
|---|
| 162 | '*' | (Num 0) <- n -> return $ Num 0 |
|---|
| 163 | '*' | (Num 1) <- m -> reduce n |
|---|
| 164 | '*' | (Num 1) <- n -> reduce m |
|---|
| 165 | '-' | (Num 0) <- n -> reduce m |
|---|
| 166 | _ -> case reduce m of |
|---|
| 167 | Just m' -> return $ Op m' c n |
|---|
| 168 | _ -> reduce n >>= \n' -> return $ Op m c n' |
|---|
| 169 | |
|---|
| 170 | r :: Maybe L -> Maybe L |
|---|
| 171 | r x = x >>= reduce |
|---|
| 172 | |
|---|
| 173 | it f x = it' f (Just x) |
|---|
| 174 | where |
|---|
| 175 | it' _ Nothing = [] |
|---|
| 176 | it' f (Just x) = x:it' f (f x) |
|---|
| 177 | |
|---|
| 178 | rchain :: L -> [L] |
|---|
| 179 | rchain = it reduce |
|---|
| 180 | |
|---|
| 181 | pchain = putStrLn . intercalate "\n-> " . map show . rchain |
|---|
| 182 | |
|---|
| 183 | lplus = Abs m $ Abs n $ Abs f $ Abs x $ App (App (Var m) (Var f)) $ App (App (Var n) (Var f)) (Var x) |
|---|
| 184 | where [m,n,f,x] = [0..3] |
|---|
| 185 | lzero = Abs f $ Abs x $ Var x |
|---|
| 186 | where [f,x] = [0,1] |
|---|
| 187 | lsucc = Abs n $ Abs f $ Abs x $ App (Var f) $ App (App (Var n) (Var f)) (Var x) |
|---|
| 188 | where [n,f,x] = [0..2] |
|---|
| 189 | lone = last $ it reduce $ App lsucc lzero |
|---|
| 190 | ltwo = last $ it reduce $ App lsucc lone |
|---|
| 191 | |
|---|
| 192 | lpred = Abs n $ Abs f $ Abs x $ App (App (App (Var n) u1) (Abs u $ Var x)) (Abs u $ Var u) |
|---|
| 193 | where |
|---|
| 194 | u1 = Abs g $ Abs h $ App (Var h) $ App (Var g) (Var f) |
|---|
| 195 | [n,f,x,g,h,u] = [0..5] |
|---|
| 196 | |
|---|
| 197 | lsub = Abs m $ Abs n $ App (App (Var n) lpred) (Var m) |
|---|
| 198 | where (m,n) = (0,1) |
|---|
| 199 | |
|---|
| 200 | ltrue = Abs 0 $ Abs 1 $ Var 0 |
|---|
| 201 | lfalse = Abs 0 $ Abs 1 $ Var 1 |
|---|
| 202 | |
|---|
| 203 | liszero = Abs n $ App (App (Var n) (Abs x lfalse)) ltrue |
|---|
| 204 | where (n,x) = (0,1) |
|---|
| 205 | |
|---|
| 206 | land = Abs 0 $ Abs 1 $ App (App (Var 0) (Var 1)) (Var 1) |
|---|
| 207 | lleq = Abs 0 $ Abs 1 $ App liszero $ App (App lsub (Var 0)) (Var 1) |
|---|
| 208 | leq = Abs 0 $ Abs 1 $ App (App land l1) l2 |
|---|
| 209 | where |
|---|
| 210 | l1 = App (App lleq (Var 0)) (Var 1) |
|---|
| 211 | l2 = App (App lleq (Var 1)) (Var 0) |
|---|
| 212 | |
|---|
| 213 | test = Abs 0 $ Abs 1 $ App (App leq xpy) ypx |
|---|
| 214 | xpy = App (App lplus (Var 0)) (Var 1) |
|---|
| 215 | ypx = App (App lplus (Var 1)) (Var 0) |
|---|
| 216 | |
|---|
| 217 | smap = Abs 5 $ AAbs 18 6 $ List (Var 18) (Abs 8$ App (Var 5) (App (Var 6) (Var 8))) |
|---|
| 218 | conss = Abs 23 $ AAbs 19 5 $ List (Op (Num 1) '+' (Var 19)) $ Shift (Var 5) (Var 19) (Abs 8 $ Var 23) |
|---|
| 219 | addones = AAbs 19 5 $ List (Op (Num 1) '+' (Var 19)) (Abs 8 Unsized) |
|---|
| 220 | nils = List (Num 0) (Abs 8 Bottom) |
|---|
| 221 | lz n = List (Num n) (Abs 8 Unsized) |
|---|
| 222 | srep n x = List (Num n) (Abs 8 x) |
|---|
| 223 | dupfst = AAbs 19 5 $ List (Op (Num 1) '+' (Var 19)) $ Shift (Var 5) (Op (Var 19) '-' (Num 1)) |
|---|
| 224 | $ Abs 8 $ App (Var 5) (Op (Var 19) '-' (Num 1)) |
|---|
| 225 | yComb = Abs 18 $ App (Abs 22 $ App (Var 18) (App (Var 22) (Var 22))) (Abs 22 $ App (Var 18) (App (Var 22) (Var 22))) |
|---|
| 226 | -- Îs,g.List s (λi.(λx.Ît,f.List (1+t) (Shift f (t-1) x)) U (g i)) |
|---|
| 227 | reverses = AAbs 18 5 $ List (Var 18) (Abs 8 $ App (Var 5) $ Op (Op (Var 18) '-' (Num 1)) '-' (Var 8) ) |
|---|
| 228 | reverse' l = case l of |
|---|
| 229 | [] -> [] |
|---|
| 230 | (x:xs) -> x:reverse' xs |
|---|
| 231 | appends = AAbs 18 5 $ AAbs 19 6 $ List (Op (Var 18) '+' (Var 19)) $ Shift (Var 6) (Var 19) (Var 5) |
|---|
| 232 | |
|---|
| 233 | headc = AAbs 18 5 $ App (Var 5) (Op (Var 18) '-' (Num 1)) |
|---|
| 234 | tailc = AAbs 18 5 $ List (Op (Var 18) '-' (Num 1)) (Var 5) |
|---|
| 235 | rall = last . it reduce |
|---|
| 236 | |
|---|
| 237 | sheads = rall $ App smap headc |
|---|
| 238 | stails = rall $ App smap tailc |
|---|