import Data.List import Control.Monad type Check a = Maybe a type Type = String type Var = String type FSym = String type FSym_Info = ([Type], Type) type Vars = Var -> Check Type type Sig = FSym -> Check FSym_Info data Term = Var Var | Fun FSym [Term] deriving (Eq, Show) failure :: Check a failure = Nothing assert :: Bool -> Check () assert p = if p then return () else failure type_check :: Sig -> Vars -> Term -> Check Type type_check sig vars (Var x) = vars x type_check sig vars (Fun f ts) = do (tys_in, ty_out) <- sig f tys_ts <- mapM (type_check sig vars) ts assert (tys_ts == tys_in) return ty_out infer_type :: Sig -> Type -> Term -> Check [(Var,Type)] infer_type sig ty = undefined type_check_eqn :: Sig -> (Term, Term) -> Check () type_check_eqn sigma = undefined data Data_Definition = Data Type [(FSym, FSym_Info)] data Function_Definition = Function FSym FSym_Info [(Term,Term)] type Functional_Prog = ([Data_Definition],[Function_Definition]) type Sig_List = [(FSym, FSym_Info)] type Defs = Sig_List type Cons = Sig_List type Equations = [(Term,Term)] data Prog_Info = Prog_Info [Type] Cons Defs Equations deriving Show process_data_definition :: Prog_Info -> Data_Definition -> Check Prog_Info process_data_definition pi@(Prog_Info tys cons defs eqs) (Data ty new_cs) = do -- check that type is fresh -- compute new types -- check distinctness of new constructor names -- check fresh constructor names -- check types of constructors -- check existence of non-recursive constructor -- return new prog info undefined process_data_definitions :: Prog_Info -> [Data_Definition] -> Check Prog_Info process_data_definitions = undefined