1
{-# OPTIONS -fglasgow-exts #-}
4
module DeBruijnCBN3 where
9
import qualified Data.Map as Map
14
raiseFrom :: Int -> Int -> Exp -> Exp
15
raiseFrom n k e = case e of
18
| otherwise -> Var (m + k)
21
App s t -> App (raiseFrom n k s) (raiseFrom n k t)
22
Lam e -> Lam $ raiseFrom (n + 1) k e
24
raise :: Int -> Exp -> Exp
27
subst :: [Exp] -> Exp -> Exp
28
subst us v = case v of
32
App s t -> App (subst us s) (subst us t)
33
Lam t -> Lam $ subst (Var 0 : map (raise 1) us) t
35
data Match a = No | DontKnow | Yes a
37
instance Monoid a => Monoid (Match a) where
40
mappend DontKnow _ = DontKnow
41
mappend (Yes _) No = No
42
mappend (Yes _) DontKnow = DontKnow
43
mappend (Yes x) (Yes y) = Yes $ mappend x y
45
data Reduction a b = NotReduced a | Reduced b
47
matchDef :: Sig -> [Clause] -> [Exp] -> Reduction [Exp] Exp
48
matchDef sig [] vs = NotReduced vs
49
matchDef sig (c : cs) vs = case m of
50
No -> matchDef sig cs vs'
51
DontKnow -> NotReduced vs'
54
(m, vs') = match sig c vs
56
match :: Sig -> Clause -> [Exp] -> (Match Exp, [Exp])
57
match sig (Clause ps v) vs
58
| length vs < nargs = (DontKnow, vs)
60
let (m, vs0') = matchPats sig ps vs0
62
Yes us -> (Yes $ subst (reverse us) v `apps` vs1, vs0' ++ vs1)
63
No -> (No, vs0' ++ vs1)
64
DontKnow -> (DontKnow, vs0' ++ vs1)
67
(vs0,vs1) = splitAt nargs vs
69
matchPats :: Sig -> [Pat] -> [Exp] -> (Match [Exp], [Exp])
70
matchPats sig [] [] = (Yes [], [])
71
matchPats sig (p : ps) (v : vs) =
72
let (m, v') = matchPat sig p v
75
DontKnow -> (DontKnow, v' : vs)
76
Yes _ -> let (ms, vs') = matchPats sig ps vs
77
in (mappend m ms, v' : vs')
79
matchPat :: Sig -> Pat -> Exp -> (Match [Exp], Exp)
80
matchPat _ VarP v = (Yes [v], v)
81
matchPat _ WildP v = (Yes [v], v)
82
matchPat sig (ConP c ps) v = case appView v' of
85
let (m, vs') = matchPats sig ps vs
87
Yes vs -> (Yes vs, Con c' `apps` vs')
88
No -> (No, Con c' `apps` vs')
89
DontKnow -> (DontKnow, Con c' `apps` vs')
90
| otherwise -> (No, v')
95
iota :: Sig -> String -> [Exp] -> Exp
96
iota sig c vs = fromMaybe (Con c `apps` vs) $ do
97
cs <- Map.lookup c sig
98
case matchDef sig cs vs of
99
NotReduced vs -> return $ Con c `apps` vs
100
Reduced v -> return $ whnf sig v
103
top v = v : map Var [0..]
105
whnf :: Sig -> Exp -> Exp
106
whnf sig v = case appView v of
107
Var n `Apps` vs -> Var n `apps` vs
108
Con c `Apps` vs -> Con c `apps` vs
109
Def c `Apps` vs -> iota sig c vs
110
Lam u `Apps` (v : vs) -> whnf sig (subst (top v) u `apps` vs)
111
Lam u `Apps` [] -> Lam u
113
eval :: Sig -> Exp -> Exp
114
eval sig v = case whnf sig v of
115
Lam u -> Lam $ eval sig u
116
App u v -> App (eval sig u) (eval sig v)