Haskell 在没有CPP的情况下,如何最好地适应阴谋集团库中的类型变化?
我想增强用户对从.cabal文件自动配置flycheck的支持 要进行此自动配置,flycheck使用的原始策略是读取.cabal文件并使用Haskell 在没有CPP的情况下,如何最好地适应阴谋集团库中的类型变化?,haskell,emacs,cabal,flycheck,Haskell,Emacs,Cabal,Flycheck,我想增强用户对从.cabal文件自动配置flycheck的支持 要进行此自动配置,flycheck使用的原始策略是读取.cabal文件并使用FlattPackageDescription。这很简单,但不考虑条件表达式,这可能会导致问题,例如,在使用较新版本的bytestring包时,不需要bytestring builder 要使用的适当界面似乎是finalizePackageDescription。这确实有效……但是它的类型签名在1.20和1.22之间发生了变化——现在,它不再使用Compil
FlattPackageDescription
。这很简单,但不考虑条件表达式,这可能会导致问题,例如,在使用较新版本的bytestring
包时,不需要bytestring builder
要使用的适当界面似乎是finalizePackageDescription
。这确实有效……但是它的类型签名在1.20和1.22之间发生了变化——现在,它不再使用CompilerId
,而是使用CompilerInfo
。不过,我希望在整个API更改过程中提供一致的支持
虽然解决方案通常是使用CPP
宏,但这些宏是由Cabal
本身提供的,flycheck
只是使用runhaskell
调用帮助文件,因此我们没有访问它们的权限
我能想到的唯一选择是创建另一个助手,首先获取Cabal
版本信息,然后为runhaskell
调用构造适当的CPP
设置,这样我们就可以这样做。这应该行得通,但看起来像是个黑客
因此,我在这里寻找其他选项,使我能够支持两个版本的界面,而不必求助于CPP
所讨论的代码是对Distribution.PackageDescription.Configuration.finalizePackageDescription的调用,如下所示:
case finalizePackageDescription [] (const True) buildPlatform buildCompilerId [] genericDesc' of
Left e -> putStrLn $ "Issue with package configuration\n" ++ show e
Right (pkgDesc, _) -> print (dumpPackageDescription pkgDesc cabalFile)
问题是第四个参数buildCompilerId
将类型从CompilerId
更改为CompilerInfo
我所实施的——尽管我很乐意考虑一个更独立的选项---是一个助手,它吐出了<代码> DuseCompilerInfo <代码>(作为一个S- EXPR,因为我们正在处理Emacs),如果它是一个最新版本的阴谋:
import Data.Version (Version (Version))
import Distribution.Simple.Utils (cabalVersion)
main :: IO ()
main =
putStrLn $ if cabalVersion >= Version [1,22] []
then "(\"-DuseCompilerInfo\")"
else "()"
然后使用该标志运行原始帮助程序,并有条件地导入新结构,并且在上面的case语句之前具有以下条件代码:
#ifdef useCompilerInfo
buildCompilerId = unknownCompilerInfo (CompilerId buildCompilerFlavor compilerVersion) NoAbiTag
#else
buildCompilerId = CompilerId buildCompilerFlavor compilerVersion
#endif
它并不漂亮,但很管用。有人告诉我,这些技巧中有一些是由于指针才起作用的。不幸的是,我开始相信,他们引入了一种新的数据类型(CompilerInfo),这就不可行了。这真的很难看,但是,通过使用
mkName
构造所需的名称,您应该始终能够使用模板Haskell方法。博客文章中提到的其他方法是否有效,可能取决于您需要编写的两个版本的代码是什么;也许在你的问题中包括它们?