Haskell中提取函数参数类型用于类型检查的实现方案咨询
解决方案
你的核心问题是混淆了状态修改(插入参数到符号表)和类型收集的逻辑——typeCheckStmt负责修改状态,但你试图用它的返回值来收集类型,这就导致了类型不匹配(它返回State ()而非State TypeT)。下面是修正后的实现:
步骤1:添加辅助函数提取参数类型
先写一个简单的辅助函数,从FunctionArg语句中提取类型:
getFunctionArgType :: Statement -> Maybe TypeT getFunctionArgType (FunctionArg _ argType) = Just argType getFunctionArgType _ = Nothing -- 处理非FunctionArg的错误情况
步骤2:修正typeCheckStmt的Function分支逻辑
在Function分支中,先提取所有参数的类型,再执行状态修改(插入参数到符号表),最后插入函数签名:
typeCheckStmt :: Scope -> TypeT -> Statement -> State (SymbolTable, SymbolTable) () typeCheckStmt scope returnType = \case Function name args returnType body -> do let newScope = scope + 1 -- 1. 提取所有参数的类型(先做类型校验,确保args都是FunctionArg) typeArgs <- case traverse getFunctionArgType args of Just ts -> pure ts Nothing -> error $ "Invalid function argument in " ++ name -- 2. 将每个参数插入当前函数的符号表(执行状态修改) traverse_ (typeCheckStmt newScope returnType) args -- 3. 插入函数签名到符号表 _ <- insert name (FunctionT typeArgs returnType) scope -- 4. 检查函数体的类型 _ <- typeCheckStmt newScope returnType body exitFunction FunctionArg name type_ -> do _ <- insert name type_ scope pure () -- 其他Statement分支的实现...
关键说明
- 类型收集不需要依赖State monad:因为
args的结构是已知的(都是FunctionArg),直接从数据结构中提取即可,不需要通过状态操作的返回值。 traverse_而非traverse:因为typeCheckStmt返回State (),我们只需要执行它的副作用(修改符号表),不需要收集返回值,所以用traverse_(忽略结果的遍历)更合适。- 错误处理:用
traverse getFunctionArgType可以提前检查是否有非FunctionArg的语句混入参数列表,避免后续逻辑出错。
内容的提问来源于stack exchange,提问作者NotAlfred
相关产品推荐
相关产品推荐

