1
{-# OPTIONS -fglasgow-exts #-}
3
module DeBruijnCBN where
8
import qualified Data.Map as Map
13
raiseFrom :: Int -> Int -> Exp -> Exp
14
raiseFrom n k e = case e of
17
| otherwise -> Var (m + k)
20
App s t -> App (raiseFrom n k s) (raiseFrom n k t)
21
Lam e -> Lam $ raiseFrom (n + 1) k e
23
raise :: Int -> Exp -> Exp
26
substUnder :: Int -> Exp -> Exp -> Exp
27
substUnder n u v = case v of
31
| otherwise -> Var (m - 1)
34
App s t -> App (substUnder n u s) (substUnder n u t)
35
Lam t -> Lam $ substUnder (n + 1) u t
37
subst :: Exp -> Exp -> Exp
40
substs :: [Exp] -> Exp -> Exp
41
substs us v = foldr subst v $ zipWith raise [0..] us
43
data Match a = No | DontKnow | Yes a
45
newtype FirstMatch a = FirstMatch { firstMatch :: Match a }
46
newtype AllMatch a = AllMatch { allMatch :: Match a }
48
instance Monoid (FirstMatch a) where
49
mempty = FirstMatch No
50
mappend (FirstMatch No) m = m
51
mappend (FirstMatch DontKnow) _ = FirstMatch DontKnow
52
mappend (FirstMatch (Yes v)) _ = FirstMatch $ Yes v
54
instance Monoid a => Monoid (AllMatch a) where
55
mempty = AllMatch $ Yes mempty
56
mappend (AllMatch No) _ = AllMatch No
57
mappend (AllMatch DontKnow) _ = AllMatch DontKnow
58
mappend (AllMatch (Yes _)) (AllMatch No) = AllMatch No
59
mappend (AllMatch (Yes _)) (AllMatch DontKnow) = AllMatch DontKnow
60
mappend (AllMatch (Yes x)) (AllMatch (Yes y)) = AllMatch $ Yes $ mappend x y
62
yes :: Match a -> Maybe a
66
matchDef :: Sig -> [Clause] -> [Exp] -> Maybe Exp
67
matchDef sig cs vs = yes $ firstMatch $ mconcat $ map (flip (match sig) vs) cs
69
match :: Sig -> Clause -> [Exp] -> FirstMatch Exp
70
match sig (Clause ps v) vs
71
| length vs < nargs = FirstMatch DontKnow
72
| otherwise = case allMatch $ matchPats sig ps vs0 of
73
Yes us -> FirstMatch $ Yes $ substs us v `apps` vs1
75
DontKnow -> FirstMatch DontKnow
78
(vs0,vs1) = splitAt nargs vs
80
matchPats :: Sig -> [Pat] -> [Exp] -> AllMatch [Exp]
81
matchPats sig ps vs = mconcat $ zipWith (matchPat sig) ps vs
83
matchPat :: Sig -> Pat -> Exp -> AllMatch [Exp]
84
matchPat _ VarP v = AllMatch $ Yes [v]
85
matchPat _ WildP v = AllMatch $ Yes [v]
86
matchPat sig (ConP c ps) v = case appView $ whnf sig v of
88
| c == c' -> matchPats sig ps vs
89
| otherwise -> AllMatch No
90
_ -> AllMatch DontKnow
92
iota :: Sig -> String -> [Exp] -> Exp
93
iota sig c vs = fromMaybe (Con c `apps` vs) $ do
94
cs <- Map.lookup c sig
95
e <- matchDef sig cs vs
98
whnf :: Sig -> Exp -> Exp
99
whnf sig v = case appView v of
100
Var n `Apps` vs -> Var n `apps` vs
101
Con c `Apps` vs -> Con c `apps` vs
102
Def c `Apps` vs -> iota sig c vs
103
Lam u `Apps` (v : vs) -> whnf sig (subst v u `apps` vs)
104
Lam u `Apps` [] -> Lam u
106
eval :: Sig -> Exp -> Exp
107
eval sig v = case whnf sig v of
108
Lam u -> Lam $ eval sig u
109
App u v -> App (eval sig u) (eval sig v)