ghc-8.10-9.6 经验报告

这是一份关于从 GHC 8.10 升级到 GHC 9.6 的经验报告,主要内容如下:

  • 升级背景:在工作中(Groq)将 GHC 版本从 8.10 升级到 9.6,并更新了依赖的 Haskell 包,其中一些变化是“破坏性的”,需要修改自身代码。
  • 两种行为:区分了应对包含破坏性变化的升级所需的两种保持行为的更改——“向前兼容的缓解措施”和“破坏性修复”。前者可在升级前进行,后者仅在升级后有效。
  • 将破坏性修复转换为向前兼容的缓解措施:可以通过使用 CPP 或“兼容性垫片”将破坏性修复转换为向前兼容的缓解措施。
  • 具体变化

    • 库的变化

      • Prelude的新导出:新版本base重新导出liftA2,导致Control.Applicative的显式导入发出警告,可选择关闭警告或删除显式导入。
      • STMonadFail实例删除:在最近的base版本中删除,可在ST中使用error替代fail
      • mtl模块的导出删除:一些mtl模块删除了与转换器相关的功能的导出,需要从其他地方导入,如Control.Monad.Trans
      • aesonAPI 变化:版本 2 将 JSON 对象的表示从HashMap Text Value更改为KeyMap Value,需要使用新 API 并进行必要的转换。部分修复可通过巧妙使用导入和本地定义作为兼容性垫片实现向前兼容。
      • I64#变化:Int64的定义从data Int64 = I64# Int#更改为data Int64 = I64# Int64#,需要进行破坏性修复或删除使用该低级表示的代码(幸运的是是向前兼容的缓解措施)。
      • xlsAPI 变化:xls库引入RowIndexColumnIndex抽象类型,需要进行破坏性修复,并可通过定义类型同义词作为兼容性垫片部分实现向前兼容,同时还添加了wsState字段,需要在构造该类型的值时进行破坏性修复。
      • flatparseAPI 变化:许多flatparse的 API 发生变化,如anyCharASCII变为anyAsciiChar,可使用兼容性模块或进行破坏性修复。
      • constraints-extrasHas变化:从类型同义词变为类型类,需要进行破坏性修复。
      • genSingletons:升级后无法使用genSingletons,需手动编写原本由 Template Haskell 生成的代码。
    • GHC 的变化

      • 简化的包含:GHC 9.0 切换到更高秩多态性的类型推断方案,导致一些表达式在 GHC 9 系列中无法通过类型检查,可通过手动 eta 展开或禁用简化的包含来缓解。
      • GHC 错误:遇到 GHC 在与存在类型相关的代码中出错的问题,通过将内部绑定提升到顶级并标记为NOINLINE来缓解。
      • 重叠模式:GHC 的模式匹配检查器的改进导致一些模式被检测为冗余,可选择使用-Wwarn=overlapping-patterns或删除冗余模式。
      • 类型*变为Type:GHC 9 系列在-Wall中引入关于使用*作为类型种类的警告,可将*替换为Data.Kind.Type
      • GADT 单本地绑定:GHC 9 系列在-Wall中引入关于在没有MonoLocalBinds的情况下对 GADT 进行模式匹配的警告,可启用MonoLocalBinds或禁用gadt-mono-local-binds警告。
    • 工具的变化

      • brittany不再维护:不再使用brittany格式化部分代码。
      • Hadrian:在启用交叉编译时,Hadrian 拒绝构建ghci,不再构建交叉编译的 GHC。
  • 经验总结:希望这份报告能衡量跟上 Haskell 生态系统中破坏性变化所需的努力,鼓励库和编译器维护者在合理的情况下避免进行破坏性更改,并在进行破坏性更改时以允许向前兼容缓解而不是破坏性修复的方式进行。同时提到了The Opaleye API breakage policy通过大量使用兼容性垫片来维护。
阅读 13
0 条评论