|
| 1 | +module Lambda where |
| 2 | + |
| 3 | +import Prelude hiding (iterate, elem) |
| 4 | + |
| 5 | +type Variable = String |
| 6 | + |
| 7 | +-- Лямбда-терм |
| 8 | +data Term = Var Variable |
| 9 | + | Abs Variable Term |
| 10 | + | App Term Term |
| 11 | + deriving (Show) |
| 12 | + |
| 13 | +-- Тип [ a ] == Типу List a |
| 14 | +-- значение [] == значению Nil |
| 15 | +-- значение [ a ] == значению Cons a Nil |
| 16 | +-- конструктор (:) == конструктору Cons |
| 17 | + |
| 18 | +-- Свободные переменные терма |
| 19 | +free (Var v) = [v] |
| 20 | +free (Abs v t) = filter (/= v) . free $ t -- /= это <<не равно>> |
| 21 | +free (App t t') = (free t) ++ (free t') |
| 22 | + |
| 23 | +binded (Var v) = [] |
| 24 | +binded (Abs v t) = v : binded t |
| 25 | +binded (App t t') = binded t ++ binded t' |
| 26 | + |
| 27 | +-- Заменить все свободные вхождения переменной var на what в терме term |
| 28 | +subst var what term = case term of |
| 29 | + Var v -> if v == var then what else term |
| 30 | + Abs v t -> if v == var then term else Abs v (subst var what t) |
| 31 | + App t t' -> App (subst var what t) (subst var what t') |
| 32 | + |
| 33 | +-- Содержит ли список элемент? |
| 34 | +elem a [] = False |
| 35 | +elem a (l:ls) = if a == l then True else elem a ls |
| 36 | + |
| 37 | +-- Любопытная функция |
| 38 | +iterate f x = (:) x $ iterate f (f x) |
| 39 | + |
| 40 | +-- Генерирует список имён, производных от v, не входящих в fv |
| 41 | +newname fv v = head . filter (\x -> not . elem x $ fv) . iterate ('_':) $ v |
| 42 | + |
| 43 | +-- Обычная бета-редукция, хендлящая переименования переменных |
| 44 | +betaReduct :: Variable -> Term -> Term -> Term |
| 45 | +betaReduct var what term = subst var what $ renameBindings (free what) term |
| 46 | + where renameBindings vars subterm = case subterm of |
| 47 | + Var _ -> subterm |
| 48 | + App t t' -> App (renameBindings vars t) (renameBindings vars t') |
| 49 | + Abs n t -> Abs nn newt |
| 50 | + where nameUsed = elem n vars |
| 51 | + nn = if nameUsed then newname (vars ++ free t) n else n |
| 52 | + newt = if nameUsed then subst n (Var nn) t else t |
| 53 | + |
| 54 | +hasRedexes (Var _) = False |
| 55 | +hasRedexes (Abs v t) = hasRedexes t |
| 56 | +hasRedexes (App (Abs _ t) t') = True |
| 57 | +hasRedexes (App t t') = hasRedexes t || hasRedexes t' |
| 58 | + |
| 59 | +-- Нормализация нормальным порядком терма term |
| 60 | +normal' :: Term -> Term |
| 61 | +normal' term = if (hasRedexes term) then normal' $ normalReduce term else term |
| 62 | + |
| 63 | +normalReduce term = case term of |
| 64 | + Var _ -> term |
| 65 | + Abs var subterm -> Abs var $ normalReduce subterm |
| 66 | + App (Abs var subterm) term' -> betaReduct var term' subterm |
| 67 | + App term term' -> if hasRedexes term |
| 68 | + then App (normalReduce term) term' |
| 69 | + else App term $ normalReduce term' |
| 70 | + |
| 71 | +-- Нормализация аппликативным порядком терма term |
| 72 | +applicative' :: Term -> Term |
| 73 | +applicative' term = if (hasRedexes term) then applicative' $ applicativeReduce term else term |
| 74 | + |
| 75 | +applicativeReduce term = case term of |
| 76 | + Var _ -> term |
| 77 | + Abs var subterm -> Abs var $ applicativeReduce subterm |
| 78 | + App term term' -> if hasRedexes term' then App term $ applicativeReduce term' else case term of |
| 79 | + Abs v subt -> betaReduct v term' subt |
| 80 | + _ -> App (applicativeReduce term) term' |
| 81 | + |
| 82 | + |
| 83 | +-- Маркер конца ресурсов |
| 84 | +data TooLoong = TooLoong deriving Show |
| 85 | + |
| 86 | +-- (*) Нормализация нормальным порядком терма term за неболее чем n шагов. |
| 87 | +-- Результат: Или числа итераций недостаточно, чтобы достичь нормальной |
| 88 | +-- формы. Или (число нерастраченных итераций, терм в нормальной форме). |
| 89 | +-- |
| 90 | +normal :: Int -> Term -> Either TooLoong (Int, Term) |
| 91 | +normal n term |
| 92 | + | n < 0 = Left TooLoong |
| 93 | + | otherwise = if (hasRedexes term) |
| 94 | + then normal (n - 1) $ normalReduce term |
| 95 | + else Right (n, term) |
| 96 | + |
| 97 | +-- (*) Аналогичная нормализация аппликативным порядком. |
| 98 | +applicative :: Int -> Term -> Either TooLoong (Int, Term) |
| 99 | +applicative n term |
| 100 | + | n < 0 = Left TooLoong |
| 101 | + | otherwise = if (hasRedexes term) |
| 102 | + then applicative (n - 1) $ applicativeReduce term |
| 103 | + else Right (n, term) |
| 104 | + |
| 105 | +-- (***) Придумайте и реализуйте обобщённую функцию, выражающую некоторое |
| 106 | +-- семейство стратегий редуцирования. В том смысле, что номальная, нормальная |
| 107 | +-- головная, нормальная слабо-головная и аппликативная стратегии |
| 108 | +-- при помощи этой функции будут выражаться некоторым элементарным образом. |
| 109 | +-- Аргумент n можно отбросить, а можно оставить. |
| 110 | +-- |
| 111 | +-- strategy = ? |
| 112 | +-- |
| 113 | +-- normal = strategy ? |
| 114 | +-- hnf = strategy ? |
| 115 | +-- whnf = strategy ? |
| 116 | +-- applicative = strategy ? |
| 117 | +-- |
| 118 | +-- Какие ещё стратегии редуцирования вы знаете? Можно ли их выразить |
| 119 | +-- при помощи этой стратегии? Если да, то как? |
| 120 | +-- Если нет, то можно ли реализовать аналогичную функцию для _всех_ |
| 121 | +-- возможных стратегий редуцирования, а не только для такого семейства? |
| 122 | +-- Если да, то как? Если нет, то почему? |
| 123 | + |
| 124 | +-------------------------------------------------------- |
| 125 | + |
| 126 | +-- Область тестирования |
| 127 | + |
| 128 | +loop' = Abs "x" $ App (Var "x") (Var "x") |
| 129 | +loop = App loop' loop' |
| 130 | + |
| 131 | +u = Abs "a" $ Abs "b" $ App (Var "a") $ App (Var "b") (Var "_b") |
| 132 | +v = Abs "a" $ Abs "b" $ App (App (Var "a") (Var "b")) (Var "_b") |
| 133 | +w = Abs "a" $ Abs "b" $ Abs "c" $ Abs "d" $ App (App (Var "a") (Var "b")) (App (Var "c") (Var "d")) |
| 134 | + |
| 135 | +main = test 100 |
| 136 | + [ ("no", normal) |
| 137 | + , ("ap", applicative) ] |
| 138 | + [ Var "a" |
| 139 | + , u |
| 140 | + , v |
| 141 | + , loop' |
| 142 | + , u `App` Var "a" |
| 143 | + , v `App` Var "a" |
| 144 | + , u `App` Var "b" |
| 145 | + , v `App` Var "b" |
| 146 | + , u `App` Var "_b" |
| 147 | + , v `App` Var "_b" |
| 148 | + , (u `App` Var "_b") `App` Var "_b" |
| 149 | + , (v `App` Var "_b") `App` Var "_b" |
| 150 | + , w |
| 151 | + , w `App` (Abs "a" (Var "a") `App` (Abs "b" $ Var "b")) |
| 152 | + , (w `App` Abs "a" (Var "b")) `App` loop |
| 153 | + , loop |
| 154 | + ] |
| 155 | + |
| 156 | +-- Если вы не понимаете как это работает, то пока и не надо |
| 157 | +pall n term = mapM_ (\(desc, reduce) -> putStr (desc ++ ": ") >> print (reduce n term)) |
| 158 | + |
| 159 | +test :: Show a => Int -> [(String, Int -> Term -> a)] -> [Term] -> IO () |
| 160 | +test n funcs = mapM_ (\term -> print term >> pall n term funcs) |
0 commit comments