Skip to content

Commit 44549f7

Browse files
committed
added de brujin representation
1 parent 1c7dc26 commit 44549f7

File tree

2 files changed

+123
-13
lines changed

2 files changed

+123
-13
lines changed

UnTyLambda/DeBrujinInterpreter.hs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
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)

UnTyLambda/Interpreter.hs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
module Lambda where
2-
3-
import Prelude hiding (iterate, elem)
1+
module UnTyLambda.Interpreter where
42

53
type Variable = String
64

@@ -30,13 +28,6 @@ subst var what term = case term of
3028
Abs v t -> if v == var then term else Abs v (subst var what t)
3129
App t t' -> App (subst var what t) (subst var what t')
3230

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-
4031
-- Генерирует список имён, производных от v, не входящих в fv
4132
newname fv v = head . filter (\x -> not . elem x $ fv) . iterate ('_':) $ v
4233

@@ -75,9 +66,11 @@ applicative' term = if (hasRedexes term) then applicative' $ applicativeReduce t
7566
applicativeReduce term = case term of
7667
Var _ -> term
7768
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'
69+
App term term' -> if hasRedexes term'
70+
then App term $ applicativeReduce term'
71+
else case term of
72+
Abs v subt -> betaReduct v term' subt
73+
_ -> App (applicativeReduce term) term'
8174

8275

8376
-- Маркер конца ресурсов

0 commit comments

Comments
 (0)