([], _) = Left ["No start function defined"]
([Function _ [] e], fs)
# e = foldr (\(Function i a e)->Let i (foldr ((o) o Lambda) id a e)) e fs
- = (\x->(e, x)) <$> runInfer (infer newMap e)
+ = (\x->(e, x)) <$> runInfer (infer preamble e)
([Function _ _ _], _) = Left ["Start cannot have arguments"]
instance toString Scheme where
toString (TVar a) = toString a
toString TInt = "Int"
toString TBool = "Bool"
- toString (TFun a b) = concat ["(", toString a, ") -> ", toString b]
+ toString (a --> b) = concat ["(", toString a, ") -> ", toString b]
:: TypeEnv :== Map [Char] Scheme
+preamble :: TypeEnv
+preamble = fromList
+ [(['_if'], Forall [['_ift']]
+ $ TBool --> TVar ['_ift'] --> TVar ['_ift'] --> TVar ['_ift'])
+ ,(['_eq'], Forall [['_eq']] $ TInt --> TInt --> TBool)
+ ,(['_mul'], Forall [['_mul']] $ TInt --> TInt --> TInt)
+ ,(['_add'], Forall [['_add']] $ TInt --> TInt --> TInt)
+ ,(['_sub'], Forall [['_sub']] $ TInt --> TInt --> TInt)
+ ]
:: Subst :== Map [Char] Type
:: Infer a :== StateT [Int] (Either [String]) a
fresh :: Infer Type
fresh = getState >>= \[s:ss]->put ss >>| pure (TVar (['v':[c\\c<-:toString s]]))
-compose :: Subst Subst -> Subst
-compose s1 s2 = 'Data.Map'.union (apply s1 <$> s2) s1
+(oo) infixr 9 :: Subst Subst -> Subst
+(oo) s1 s2 = 'Data.Map'.union (apply s1 <$> s2) s1
class Substitutable a where
apply :: Subst a -> a
instance Substitutable Type where
apply s t=:(TVar v) = fromMaybe t (get v s)
- apply s (TFun t1 t2) = on TFun (apply s) t1 t2
+ apply s (t1 --> t2) = apply s t1 --> apply s t2
apply _ x = x
ftv (TVar v) = [v]
- ftv (TFun t1 t2) = on union ftv t1 t2
+ ftv (t1 --> t2) = on union ftv t1 t2
ftv _ = []
instance Substitutable Scheme where
occursCheck a = isMember a o ftv
unify :: Type Type -> Infer Subst
-unify (TFun l r) (TFun l` r`)
+unify (l --> r) (l` --> r`)
= unify l l`
>>= \s1->on unify (apply s1) r r`
- >>= \s2->pure (compose s1 s2)
-unify (TVar a) t = bind a t
-unify t (TVar a) = bind a t
+ >>= \s2->pure (s1 oo s2)
+unify (TVar a) (TVar t)
+ | a == t = pure newMap
+unify (TVar a) t
+ | occursCheck a t = liftT (Left ["Infinite type: ", toString a, " to ", toString t])
+ = pure (singleton a t)
+unify t (TVar a) = unify (TVar a) t
unify TInt TInt = pure newMap
unify TBool TBool = pure newMap
unify t1 t2 = liftT (Left ["Cannot unify: ", toString t1, " with ", toString t2])
-bind :: [Char] Type -> Infer Subst
-bind a (TVar t) | a == t = pure newMap
-bind a t
- | occursCheck a t = liftT (Left ["Infinite type: ", toString a, " and ", toString t])
- = pure (singleton a t)
-
instantiate :: Scheme -> Infer Type
instantiate (Forall as t)
= sequence [fresh\\_<-as]
= fresh
>>= \tv-> infer env e1
>>= \(s1, t1)->infer (apply s1 env) e2
- >>= \(s2, t2)->unify (apply s2 t1) (TFun t2 tv)
- >>= \s3-> pure (compose (compose s3 s2) s1, apply s3 tv)
+ >>= \(s2, t2)->unify (apply s2 t1) (t2 --> tv)
+ >>= \s3-> pure (s1 oo s2 oo s3, apply s3 tv)
infer env (Lambda x b)
= fresh
>>= \tv-> infer ('Data.Map'.put x (Forall [] tv) env) b
- >>= \(s1, t1)->pure (s1, TFun (apply s1 tv) t1)
-infer env (Builtin c a) = undef
+ >>= \(s1, t1)->pure (s1, apply s1 tv --> t1)
+//infer env (Let x e1 e2)
+// = infer env e1
+// >>= \(s1, t1)->infer ('Data.Map'.put x (generalize (apply s1 env) t1) env) e2
+// >>= \(s2, t2)->pure (s1 oo s2, t2)
infer env (Let x e1 e2)
- = infer env e1
- >>= \(s1, t1)->let env` = apply s1 env in infer ('Data.Map'.put x (generalize env` t1) env) e2
- >>= \(s2, t2)->pure (compose s1 s2, t2)
+ = fresh
+ >>= \tv-> infer ('Data.Map'.put x (Forall [] tv) env) e1
+ >>= \(s1, t1)->infer ('Data.Map'.put x (generalize (apply s1 env) t1) env) e2
+ >>= \(s2, t2)->pure (s1 oo s2, t2)