1 implementation module check
5 import Control.Monad => qualified join
6 import Control.Monad.State
7 import Control.Monad.Trans
8 import Control.Monad.Writer
13 import Data.Map => qualified put, union, difference, find, updateAt
21 check :: ![Either TypeDef Function] -> Either [String] (Expression, [([Char], Scheme)])
23 # dups = filter (\x->length x > 1) (groupBy (\(Function i _ _) (Function j _ _)->i == j) functions)
24 | length dups > 0 = Left ["Duplicate functions: ":[toString n\\[(Function n _ _):_]<-dups]]
25 = case partition (\a->a=:(Function ['start'] _ _)) functions of
26 ([], _) = Left ["No start function defined"]
27 ([Function _ [] e:_], fs)
28 # e = makeExpression fs e
29 = tuple e <$> runInfer (infer (fromList (conses ++ builtin)) e)
30 ([Function _ _ _:_], _) = Left ["Start cannot have arguments"]
32 functions = rights tdfs
33 conses = flatten $ map (\(TypeDef n t cs)->
34 let cons = Forall t o foldr (-->) (foldl TApp (TVar n) (map TVar t))
35 in map (appSnd cons) cs) $ lefts tdfs
37 [(['_if'], Forall [['a']] $ TBool --> TVar ['a'] --> TVar ['a'] --> TVar ['a'])
38 ,(['_eq'], Forall [] $ TInt --> TInt --> TBool)
39 ,(['_mul'], Forall [] $ TInt --> TInt --> TInt)
40 ,(['_add'], Forall [] $ TInt --> TInt --> TInt)
41 ,(['_sub'], Forall [] $ TInt --> TInt --> TInt)
42 ,(['_div'], Forall [] $ TInt --> TInt --> TInt)
45 makeExpression :: [Function] Expression -> Expression
46 makeExpression fs start = foldr mkExpr start $ scc $ map (appSnd vars) nicefuns
48 mkExpr :: [[Char]] -> (Expression -> Expression)
49 mkExpr scc = Let [(l, e)\\(l, e)<-nicefuns, s<-scc | s == l]
51 nicefuns :: [([Char], Expression)]
52 nicefuns = [(l, foldr ((o) o Lambda) id i e)\\(Function l i e)<-fs]
54 vars :: Expression -> [[Char]]
56 vars (App l r) = vars l ++ vars r
57 vars (Lambda l e) = flt l e
58 vars (Let ns e) = flatten [[v\\v<-vars e | not (isMember v (map fst ns))]:map (uncurry flt) ns]
61 flt i e = [v\\v<-vars e | v <> i]
63 instance toString Scheme where
64 toString (Forall [] t) = toString t
65 toString (Forall as t) = concat ["A.", join " " (map toString as), ": ", toString t]
67 :: TypeEnv :== Map [Char] Scheme
68 :: Subst :== Map [Char] Type
70 :: Infer a :== StateT [Int] (WriterT [([Char], Scheme)] (Either [String])) a
72 runInfer :: (Infer (Subst, Type)) -> Either [String] [([Char], Scheme)]
73 runInfer i = case runWriterT (evalStateT i [0..]) of
75 Right ((s, t), w) = pure [(['start'], generalize newMap (apply s t)):w]
78 fresh = getState >>= \[s:ss]->put ss >>| pure (TVar (['v':[c\\c<-:toString s]]))
80 (oo) infixl 9 :: Subst Subst -> Subst
81 (oo) s1 s2 = 'Data.Map'.union (apply s1 <$> s2) s1
83 class Substitutable a where
87 instance Substitutable Type where
88 apply s t=:(TVar v) = fromMaybe t (get v s)
89 apply s (t1 --> t2) = apply s t1 --> apply s t2
90 apply s (TApp t1 t2) = TApp (apply s t1) (apply s t2)
94 ftv (t1 --> t2) = on union ftv t1 t2
95 ftv (TApp t1 t2) = on union ftv t1 t2
98 instance Substitutable Scheme where
99 apply s (Forall as t) = Forall as $ apply (foldr del s as) t
100 ftv (Forall as t) = difference (ftv t) (removeDup as)
102 instance Substitutable TypeEnv where
103 apply s env = apply s <$> env
104 ftv env = ftv (elems env)
106 instance Substitutable [a] | Substitutable a where
107 apply s l = apply s <$> l
108 ftv t = foldr (union o ftv) [] t
110 occursCheck :: [Char] -> (a -> Bool) | Substitutable a
111 occursCheck a = isMember a o ftv
113 err :: [String] -> Infer a
114 err e = liftT (liftT (Left e))
116 unify :: Type Type -> Infer Subst
117 unify (l --> r) (l` --> r`)
119 >>= \s1->on unify (apply s1) r r`
120 >>= \s2->pure (s1 oo s2)
121 unify (TVar a) (TVar t)
122 | a == t = pure newMap
124 | occursCheck a t = err ["Infinite type: ", toString a, " to ", toString t]
125 = pure (singleton a t)
126 unify t (TVar a) = unify (TVar a) t
127 unify TInt TInt = pure newMap
128 unify TBool TBool = pure newMap
129 unify (TApp l r) (TApp l` r`)
131 >>= \s1->on unify (apply s1) r r`
132 >>= \s2->pure (s1 oo s2)
133 unify t1 t2 = err ["Cannot unify: ", toString t1, " with ", toString t2]
135 unifyl :: [Type] -> Infer Subst
136 unifyl [t1,t2:ts] = unify t1 t2 >>= \s->unifyl (map (apply s) [t2:ts])
137 unifyl _ = pure newMap
139 instantiate :: Scheme -> Infer Type
140 instantiate (Forall as t)
141 = sequence [fresh\\_<-as]
142 >>= \as`->pure (apply (fromList $ zip2 as as`) t)
144 generalize :: TypeEnv Type -> Scheme
145 generalize env t = Forall (difference (ftv t) (ftv env)) t
147 infer :: TypeEnv Expression -> Infer (Subst, Type)
148 infer env (Lit (Int _)) = pure (newMap, TInt)
149 infer env (Lit (Bool _)) = pure (newMap, TBool)
150 infer env (Var x) = maybe (err ["Unbound variable: ", toString x])
151 (\s->tuple newMap <$> instantiate s) $ get x env
152 infer env (App e1 e2)
154 >>= \tv-> infer env e1
155 >>= \(s1, t1)->infer (apply s1 env) e2
156 >>= \(s2, t2)->unify (apply s2 t1) (t2 --> tv)
157 >>= \s3-> pure (s3 oo s2 oo s1, apply s3 tv)
158 infer env (Lambda x b)
160 >>= \tv-> infer ('Data.Map'.put x (Forall [] tv) env) b
161 >>= \(s1, t1)->pure (s1, apply s1 tv --> t1)
163 //infer env (Let [(x, e1)] e2)
165 // >>= \(s1, t1)->infer ('Data.Map'.put x (generalize (apply s1 env) t1) env) e2
166 // >>= \(s2, t2)->liftT (tell [(x, Forall [] t1)])
167 // >>| pure (s1 oo s2, t2)
169 //infer env (Let [(x, e1)] e2)
171 // >>= \tv-> let env` = 'Data.Map'.put x (Forall [] tv) env
173 // >>= \(s1,t1)-> infer ('Data.Map'.put x (generalize (apply s1 env`) t1) env`) e2
174 // >>= \(s2, t2)->pure (s1 oo s2, t2)
176 infer env (Let xs e2)
177 # (ns, bs) = unzip xs
178 = sequence [fresh\\_<-ns]
179 >>= \tvs-> let env` = foldr (\(k, v)->'Data.Map'.put k (Forall [] v)) env (zip2 ns tvs)
180 in unzip <$> sequence (map (infer env`) bs)
181 >>= \(ss,ts)-> unifyl ts
182 >>= \s-> liftT (tell [(n, generalize (apply s env`) t)\\t<-ts & n<-ns])
183 >>| let env`` = foldr (\(n, s, t) m->'Data.Map'.put n (generalize (apply s env`) t) m) env` (zip3 ns ss ts)
185 >>= \(s2, t2)->pure (s oo s2, t2)