|
| 1 | +-- Type checker for dependent types from Thierry Coquand: |
| 2 | +-- http://www.cse.chalmers.se/~coquand/conv1.hs |
| 3 | +-- added some comments to ease understanding |
| 4 | + |
| 5 | + |
| 6 | +type Id = String |
| 7 | + |
| 8 | +data Exp = Var Id |
| 9 | + | App Exp Exp |
| 10 | + | Type |
| 11 | + | Abs Id Exp |
| 12 | + | Pi Id Exp Exp |
| 13 | + | Let Id Exp Exp Exp |
| 14 | + |
| 15 | +data Val = VGen Int |
| 16 | + | VApp Val Val |
| 17 | + | VType |
| 18 | + | VAbs FVal |
| 19 | + | VPi Val FVal |
| 20 | + |
| 21 | + |
| 22 | +type FVal = (Id,Exp,Env) |
| 23 | +type Env = [(Id,Val)] |
| 24 | + |
| 25 | + |
| 26 | +update :: Env -> Id -> Val -> Env |
| 27 | +update env x u = (x,u):env |
| 28 | + |
| 29 | + |
| 30 | +lookUp :: Id -> Env -> Val |
| 31 | +lookUp x ((y,u):env) = |
| 32 | + if x == y then u |
| 33 | + else lookUp x env |
| 34 | +lookUp x [] = error"lookUp" |
| 35 | + |
| 36 | + |
| 37 | + |
| 38 | +-- the whnf algorithm |
| 39 | + |
| 40 | +fapp :: FVal -> Val -> Val |
| 41 | +fapp (x,e,env) u = eval (update env x u) e |
| 42 | + |
| 43 | + |
| 44 | +app :: Val -> Val -> Val |
| 45 | +app (VAbs f) = fapp f -- can reduce with beta-reduction |
| 46 | +app v = VApp v -- cannot reduce any further, so store it as value |
| 47 | + |
| 48 | + |
| 49 | +eval :: Env -> Exp -> Val |
| 50 | +eval env e = case e of |
| 51 | + Var x -> lookUp x env |
| 52 | + App e1 e2 -> app (eval env e1) (eval env e2) |
| 53 | + Let x e1 _ e3 -> eval (update env x (eval env e1)) e3 |
| 54 | + Type -> VType |
| 55 | + Abs x e1 -> VAbs (x,e1,env) |
| 56 | + Pi x a b -> VPi (eval env a) (x,b,env) -- evaluate the type annotation |
| 57 | + |
| 58 | + |
| 59 | + |
| 60 | +-- the conversion algorithm; the integer is |
| 61 | +-- used to represent the introduction of a fresh variable |
| 62 | +-- VGen == gensym. seems to have a problem because k is not used as a |
| 63 | +-- state. |
| 64 | + |
| 65 | +eqVal :: (Int,Val,Val) -> Bool |
| 66 | +eqVal (k,u1,u2) = |
| 67 | + case (u1,u2) of |
| 68 | + (VType,VType) -> True |
| 69 | + (VApp t1 w1,VApp t2 w2) -> eqVal (k,t1,t2) && eqVal (k,w1,w2) |
| 70 | + (VGen k1,VGen k2) -> k1 == k2 |
| 71 | + (VAbs f1,VAbs f2) -> |
| 72 | + let v = VGen k |
| 73 | + in eqVal (k+1,fapp f1 v,fapp f2 v) |
| 74 | + (VPi w1 f1,VPi w2 f2) -> |
| 75 | + let v = VGen k |
| 76 | + in eqVal (k,w1,w2) && eqVal (k+1,fapp f1 v,fapp f2 v) |
| 77 | + _ -> False |
| 78 | + |
| 79 | + |
| 80 | + |
| 81 | +------------------ type-checking and type inference --------------------- |
| 82 | + |
| 83 | +-- top level: check that expression e has the type VType |
| 84 | +checkType :: (Int,Env,Env) -> Exp -> Bool |
| 85 | +checkType (k,rho,gamma) e = checkExp (k,rho,gamma) e VType |
| 86 | + |
| 87 | + |
| 88 | + |
| 89 | +-- check an expression (e) against a type (v) |
| 90 | +checkExp :: (Int,Env,Env) -> Exp -> Val -> Bool |
| 91 | +checkExp (k,rho,gamma) e v = |
| 92 | + case (e,v) of |
| 93 | + (Abs x e1,VPi w f) -> |
| 94 | + let v = VGen k |
| 95 | + in checkExp (k+1,update rho x v,update gamma x w) e1 (fapp f v) |
| 96 | + (Pi x a b,VType) -> |
| 97 | + checkType (k,rho,gamma) a && |
| 98 | + checkType (k+1,update rho x (VGen k),update gamma x (eval rho a)) b |
| 99 | + (Let x e1 e2 e3,v) -> |
| 100 | + checkType (k,rho,gamma) e1 && |
| 101 | + let v1 = eval rho e1 |
| 102 | + in checkExp (k,rho,gamma) e2 v1 && |
| 103 | + checkExp (k,update rho x (eval rho e1),update gamma x (eval rho e2)) e3 v |
| 104 | + _ -> eqVal (k, inferExp (k,rho,gamma) e, v) |
| 105 | + |
| 106 | + |
| 107 | + |
| 108 | + |
| 109 | +-- synthesis a type from expression |
| 110 | +inferExp :: (Int,Env,Env) -> Exp -> Val |
| 111 | +inferExp (k,rho,gamma) e = |
| 112 | + case e of |
| 113 | + Var id -> lookUp id gamma |
| 114 | + App e1 e2 -> |
| 115 | + case (inferExp (k,rho,gamma) e1) of |
| 116 | + VPi w f -> |
| 117 | + if checkExp (k,rho,gamma) e2 w |
| 118 | + then fapp f (eval rho e2) |
| 119 | + else error"application error" |
| 120 | + _ -> error"application, expected Pi" |
| 121 | + Type -> VType |
| 122 | + _ -> error"cannot infer type" |
| 123 | + |
0 commit comments