Haskell如何忽略未解析导入 强制编译适配自动测评系统需求
问题背景
搭建自动测评系统对学生作业自动评分时,学生提交的代码常包含VSCode自动插入的未使用无效导入语句,对应模块在测试环境不存在、触发编译失败,需要实现仅在导入的符号实际被使用时才抛出解析错误,忽略未使用的无效导入报错。
典型报错示例如下:
Submission.hs:5:1: error: Failed to load interface for ‘GHC.CmmToAsm.PPC.Instr’ Use -v to see a list of the files searched for.
解决方案
GHC编译流程中模块解析步骤早于类型检查,没有内置编译参数可以直接跳过不存在模块的导入错误,但可以通过以下两种方案实现需求:
方案1:预处理移除未使用导入(最稳妥)
编译前对学生提交的代码做静态处理,自动删除未使用的导入语句:
- 可以用
hlint工具配合自动重构功能,执行hlint --refactor --apply Submission.hs即可自动移除所有未使用的导入 - 也可以用GHC自带的
-ddump-minimal-imports参数生成代码实际需要的最小导入列表,替换原文件中的导入块
方案2:添加Dummy空模块适配(最贴合需求)
完全符合「仅用到导入符号时才报错」的要求,操作如下:
- 收集所有历史出现过的无效导入模块名,在测评环境中创建对应路径的空模块,比如对应报错中的模块,创建
GHC/CmmToAsm/PPC/Instr.hs文件,内容仅保留一行module GHC.CmmToAsm.PPC.Instr where - 编译时通过
-i<dummy模块根目录>参数将空模块所在目录加入GHC搜索路径 - 此时如果导入的模块未被实际使用,编译不会抛出任何错误;如果代码中实际用到了该模块下的符号,才会抛出「不在作用域内」的报错,完全匹配需求
注意事项
-fdefer-out-of-scope-variables参数仅能延迟符号未定义的报错到运行时,无法处理模块不存在的编译阶段错误,不能直接解决该问题。
内容的提问来源于stack exchange,提问作者Lorenzo
相关产品推荐
相关产品推荐

