You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 15:42:48