|
| 1 | +module UnTyLambda.DeBrujinInterpreter where |
| 2 | + |
| 3 | +import qualified UnTyLambda.Interpreter as I (Term(..), Variable, free) |
| 4 | + |
| 5 | +import Control.Monad (liftM) |
| 6 | +import System.IO.Unsafe (unsafePerformIO) |
| 7 | + |
| 8 | +assoc key [] = Nothing |
| 9 | +assoc key (a:alist) |
| 10 | + | key == (fst a) = Just a |
| 11 | + | otherwise = assoc key alist |
| 12 | + |
| 13 | + |
| 14 | +acons newkey newval alist = (newkey, newval) : alist |
| 15 | + |
| 16 | +data DBTerm = Var Int |
| 17 | + | Abs DBTerm |
| 18 | + | App DBTerm DBTerm |
| 19 | + deriving (Show, Read) |
| 20 | + |
| 21 | +getJust (Just a) = a |
| 22 | + |
| 23 | +type Context = [(I.Variable, Int)] |
| 24 | + |
| 25 | +removenames :: Context -> I.Term -> DBTerm |
| 26 | +removenames = removenames' 0 |
| 27 | + where removenames' n ctx (I.App lt rt) = App (removenames' n ctx lt) (removenames' n ctx rt) |
| 28 | + removenames' n ctx (I.Abs name subterm) = Abs (removenames' (n + 1) (acons name (- (n + 1)) ctx) subterm) |
| 29 | + removenames' n ctx (I.Var name) = let num = n + (snd . getJust $ assoc name ctx) |
| 30 | + in Var num |
| 31 | + |
| 32 | + |
| 33 | +getDeBrujin :: I.Term -> (DBTerm, Context) |
| 34 | +getDeBrujin term = (removenames context term, context) |
| 35 | + where context = getContext 0 $ I.free term |
| 36 | + getContext n (x:xs) = (x,n) : (getContext (n + 1) xs) |
| 37 | + getContext n [] = [] |
| 38 | + |
| 39 | +-- restorenames :: Context -> DBTerm -> I.Term |
| 40 | +-- restorenames ctx term = restorenames' 0 |
| 41 | +-- where restorenames' n ctx (I.App lt rt) = App (restorenames' n ctx lt) (restorenames' n ctx rt) |
| 42 | +-- restorenames' n ctx (I.Abs name subterm) = Abs (restorenames' (n + 1) (acons name (- (n + 1)) ctx) subterm) |
| 43 | +-- restorenames' n ctx (I.Var name) = let num = n + (snd . getJust $ assoc name ctx) |
| 44 | +-- in Var num |
| 45 | + |
| 46 | +shift' d c term = case term of |
| 47 | + (Var num) -> Var $ if num < c |
| 48 | + then num |
| 49 | + else num + d |
| 50 | + (Abs subterm) -> Abs $ shift' d (c + 1) subterm |
| 51 | + (App t1 t2) -> App (shift' d c t1) $ shift' d c t2 |
| 52 | + |
| 53 | +shift d = shift' d 0 |
| 54 | + |
| 55 | + |
| 56 | +subst what var term = case term of |
| 57 | + (Var num) -> if num == var |
| 58 | + then what |
| 59 | + else term |
| 60 | + (App t1 t2) -> App (subst what var t1) (subst what var t2) |
| 61 | + (Abs subterm) -> Abs $ subst (shift 1 what) (var + 1) subterm |
| 62 | + |
| 63 | +betaReduct :: DBTerm -> DBTerm -> DBTerm |
| 64 | +betaReduct what = shift (-1) . subst (shift 1 what) 0 |
| 65 | + |
| 66 | +hasRedexes (Var _) = False |
| 67 | +hasRedexes (Abs t) = hasRedexes t |
| 68 | +hasRedexes (App (Abs t) t') = True |
| 69 | +hasRedexes (App t t') = hasRedexes t || hasRedexes t' |
| 70 | + |
| 71 | +-- Нормализация нормальным порядком терма term |
| 72 | +normal' :: DBTerm -> DBTerm |
| 73 | +normal' term = if (hasRedexes term) then normal' $ normalReduce term else term |
| 74 | + |
| 75 | +normalReduce term = case term of |
| 76 | + Var _ -> term |
| 77 | + Abs subterm -> Abs $ normalReduce subterm |
| 78 | + App (Abs subterm) term' -> betaReduct term' subterm |
| 79 | + App term term' -> if hasRedexes term |
| 80 | + then App (normalReduce term) term' |
| 81 | + else App term $ normalReduce term' |
| 82 | + |
| 83 | +-- Нормализация аппликативным порядком терма term |
| 84 | +applicative' :: DBTerm -> DBTerm |
| 85 | +applicative' term = if (hasRedexes term) then applicative' $ applicativeReduce term else term |
| 86 | + |
| 87 | +applicativeReduce term = case term of |
| 88 | + Var _ -> term |
| 89 | + Abs subterm -> Abs $ applicativeReduce subterm |
| 90 | + App term term' -> if hasRedexes term' |
| 91 | + then App term $ applicativeReduce term' |
| 92 | + else case term of |
| 93 | + Abs subt -> betaReduct term' subt |
| 94 | + _ -> App (applicativeReduce term) term' |
| 95 | + |
| 96 | + |
| 97 | +-- Маркер конца ресурсов |
| 98 | +data TooLoong = TooLoong deriving Show |
| 99 | + |
| 100 | +-- (*) Нормализация нормальным порядком терма term за неболее чем n шагов. |
| 101 | +-- Результат: Или числа итераций недостаточно, чтобы достичь нормальной |
| 102 | +-- формы. Или (число нерастраченных итераций, терм в нормальной форме). |
| 103 | +-- |
| 104 | +normal :: Int -> DBTerm -> Either TooLoong (Int, DBTerm) |
| 105 | +normal n term |
| 106 | + | n < 0 = Left TooLoong |
| 107 | + | otherwise = if (hasRedexes term) |
| 108 | + then normal (n - 1) $ normalReduce term |
| 109 | + else Right (n, term) |
| 110 | + |
| 111 | +-- (*) Аналогичная нормализация аппликативным порядком. |
| 112 | +applicative :: Int -> DBTerm -> Either TooLoong (Int, DBTerm) |
| 113 | +applicative n term |
| 114 | + | n < 0 = Left TooLoong |
| 115 | + | otherwise = if (hasRedexes term) |
| 116 | + then applicative (n - 1) $ applicativeReduce term |
| 117 | + else Right (n, term) |
0 commit comments