dataType = TInt-- 整数 | TFunTypeType-- 関数:引数の型、結果の型 | TVarInt-- 型変数:識別番号 deriving (Eq) instanceShowTypewhere show TInt = "Int" show (TFun p e) = pp p ++ " -> " ++ show e where pp fun@(TFun _ _) = "(" ++ show fun ++ ")" pp t = show t show (TVar i) = "t" ++ show i
-- (next var index, {index=>type}) typeVarInfo = (Int, MapIntType)
infer :: [(String, Type)] -> Expr -> Type infer env expr = runST $ do varInfoRef <- newSTRef (0, empty) t <- doInfer (fromList env) varInfoRef expr (_, varDict) <- readSTRef varInfoRef return $ refer t varDict
doInfer :: Env -> STRef s VarInfo -> Expr -> ST s Type doInfer env varInfoRef expr = case expr of Natural i -> return TInt Var x -> do case lookup x env of Just t -> return t Nothing -> error ("not found: " ++ x) Fun parm e -> do tparm <- createVar varInfoRef te <- doInfer (insert parm tparm env) varInfoRef e return $ TFun tparm te App f arg -> do funType <- doInfer env varInfoRef f argType <- doInfer env varInfoRef arg retType <- createVar varInfoRef unify funType (TFun argType retType) varInfoRef return retType
unifyVar :: Int -> Type -> STRef s VarInfo -> ST s () unifyVar index type2 varInfoRef = do isOccur <- occur type2 index varInfoRef if isOccur then error "occurs error" elsedo (nextIdx, varMap) <- readSTRef varInfoRef case lookup index varMap of Just vt -> unify vt type2 varInfoRef Nothing -> writeSTRef varInfoRef (nextIdx, insert index type2 varMap)
出現確認
-- TypeInferencer.hs occur :: Type -> Int -> STRef s VarInfo -> ST s Bool occur (TFun p e) n varInfoRef = (||) <$> occur p n varInfoRef <*> occur e n varInfoRef occur (TVar i) n varInfoRef | i == n = return True | otherwise = do (_, varMap) <- readSTRef varInfoRef case lookup i varMap of Just vt -> occur vt n varInfoRef Nothing -> return False occur _ _ _ = return False
細々
-- TypeInferencer.hs createVar :: STRef s VarInfo -> ST s Type createVar varInfoRef = do (nextIdx, varMap) <- readSTRef varInfoRef writeSTRef varInfoRef (nextIdx + 1, varMap) return $ TVar nextIdx
refer :: Type -> MapIntType -> Type refer (TFun p e) varMap = TFun (refer p varMap) (refer e varMap) refer t@(TVar v) varMap = case lookup v varMap of Just vt -> refer vt varMap Nothing -> t refer t varMap = t
cannotUnify t1 t2 varInfoRef = do (_, varMap) <- readSTRef varInfoRef error ("cannot unify: " ++ show (refer t1 varMap) ++ " <=> " ++ show (refer t2 varMap))