弃用或隐藏第三方库中的模块或函数

Deprecate or shadow a module or function from a third-party library

在我们的项目(一个包含可执行文件和库部分的阴谋集团项目)中,我们有时会实现 "safer" 或标准函数的改进版本,例如base 并在新命名空间中导出模块的调整版本,例如

module Data.Foo.Extended (module Data.Foo, foo) where
import Data.Foo hiding (foo)
foo = someSaferVersionOfFoo

这使我们能够使用更好的 API 而无需进行大的重构(我们可以逐步转移到代码库其他部分的 Data.Foo.Extended)。

但是一旦我们决定移动到 *.Extended 任何地方,我们希望有一种方法可以在导入遗留(标准)模块时(或者可能在使用某些功能时)发出警告,以便换棍子。

DEPRECATED pragma 将不起作用,因为我们不拥有我们正在弃用的代码

有什么巧妙的方法可以:

Cabal 文件中的 mixins 字段(我相信 Stack 也支持它)可以用来重命名、隐藏或隐藏模块。

例如,假设我们有一个带有 MyPrelude 模块的便利库或包,我们可以通过这种方式隐藏另一个库的标准 Prelude

library
  -- in this library, Prelude is really MyPrelude
  exposed-modules:     Foo 
  hs-source-dirs:      lib
  default-language:    Haskell2010
  build-depends:       
    base ^>=4.12.0.0,
    myprelude
  mixins:
    -- switcheroo happens here
    base hiding (Prelude),
    myprelude (MyPrelude as Prelude),

-- internal convenience library, could be an external package
library myprelude
  -- MyPrelude uses Prelude normally, might even re-export it
  exposed-modules:     MyPrelude 
  hs-source-dirs:      lib-prelude
  default-language:    Haskell2010
  build-depends:       base ^>=4.12.0.0

也可以将 build-dependsmixins 字段放入 common stanzas 以避免在多个 executables/libraries:

中隐藏同一模块时重复
common tweaked-prelude
  build-depends:       
    base ^>=4.12.0.0,
    myprelude
  mixins:
    base hiding (Prelude),
    myprelude (MyPrelude as Prelude),

library
  import: tweaked-prelude
  exposed-modules:     Foo 
  hs-source-dirs:      lib
  default-language:    Haskell2010