import ast
-check :: AST -> Either [String] AST
+//Start = runRWST (infer (AST [(Function ['s','t','a','r','t'] [] (Lit (Int 42)))])
+Start = runRWST (infer (TypeEnv 'DM'.newMap) t) [] {tiSupply=0,tiSubst='DM'.newMap}
+where
+ t = Function ['start'] [] (Lit (Int 42))
+
+check :: AST -> Either [String] (Type, AST)
check (AST fs) = case find (\f->f=:(Function ['start'] [] _)) fs of
Nothing = Left ["No start function defined"]
- Just _ = Right (AST fs)
+ Just _ = Right undef/*case runRWST (infer fs) [] 'DM'.newMap of
+ Left e = Left e
+ Right (a, s, _) = Right (a, s)
+*/
:: Type
= TVar [Char]
| TBool
| TChar
| TFun Type Type
+
instance == Type where
(==) (TVar a) (TVar b) = a == b
(==) TInt TInt = True
(==) TChar TChar = True
(==) (TFun a1 a2) (TFun b1 b2) = a1 == b1 && a2 == b2
(==) _ _ = False
+
instance toString Type where
toString (TVar s) = toString s
toString TInt = "Int"
toString TBool = "Bool"
toString TChar = "Char"
toString (TFun t1 t2) = toString t1 +++ " -> " +++ toString t2
+
:: Scheme = Scheme [[Char]] Type
class Types a where
ftv :: a -> [[Char]]
apply :: Subst a -> a
+
instance Types Type where
ftv (TVar n) = [n]
ftv TInt = []
Just t = t
apply s (TFun t1 t2) = TFun (apply s t1) (apply s t2)
apply s t = t
+
instance Types Scheme where
ftv (Scheme vars t) = difference (ftv t) vars
apply s (Scheme vars t) = Scheme vars (apply (foldr 'DM'.del s vars) t)
+
instance Types [a] | Types a where
ftv l = foldr union [] (map ftv l)
apply s l = map (apply s) l
>>= \nvars->pure (apply ('DM'.fromList (zip2 vars nvars)) t)
class infer a :: TypeEnv a -> TI (Subst, Type)
+
instance infer Value where
infer _ (Int _) = pure ('DM'.newMap, TInt)
infer _ (Bool _) = pure ('DM'.newMap, TBool)
infer _ (Char _) = pure ('DM'.newMap, TChar)
+
instance infer Expression where
infer e (Lit a) = infer e a
infer (TypeEnv env) (Var v) = case 'DM'.get v env of
>>= \(s1, t1)->infer (apply s1 env) e2
>>= \(s2, t2)->mgu (apply s2 t1) (TFun t2 tv)
>>= \s3->pure (composeSubst s3 (composeSubst s2 s1), apply s3 tv)
- //infer env (Lambda s e)
- // = newTyVar ['l']
- // >>= \tv->pure undef//inEnv (s, Forall [] tv) (infer e)
- // >>= \t-> pure (TFun tv t)
+ infer env (Lambda s e)
+ = newTyVar ['l']
+ >>= \tv->
+ let (TypeEnv env`) = remove env s
+ env`` = TypeEnv ('DM'.union env` ('DM'.singleton s (Scheme [] tv)))
+ in infer env`` e
+ >>= \(s1, t1)->pure (s1, TFun (apply s1 tv) t1)
+
+instance infer Function where
+ infer env (Function name [] body)
+ = infer env body
+
+typeInference :: ('DM'.Map [Char] Scheme) Expression -> TI Type
+typeInference env e = uncurry apply <$> infer (TypeEnv env) e