cabal ,或 more recently GHC itself , 预定义允许检查使用哪个库的版本的 CPP 宏。它在简单的例子中很容易工作,比如
#if MIN_VERSION_base(4,0,0)
... code that works with base-4 ...
#else
... code that works with base-3 ...
#endif
但是,CPP 宏名称比 Cabal 包名称更受限制,因此以下内容不起作用:
#if !MIN_VERSION_quickcheck-instances(0,3,17)
instance Arbitrary SBS.ShortByteString where arbitrary = fmap SBS.pack arbitrary
#endif
错误:在标记“(”之前缺少二元运算符
#if !MIN_VERSION_quickcheck-instances(0,3,17)
^
|
18 | #if !MIN_VERSION_quickcheck-instances(0,3,17)
| ^
“gcc”在“C 预处理器”阶段失败。 (退出代码:1)
似乎没有正确记录如何处理这样的库名称。
最佳答案
简答 : 连字符 ( -
) 被替换为下划线 ( _
)。
据我所知,宏是在 generatePackageVersionMacros
function of the DriverPipeline.hs
file 中生成的。 :
generatePackageVersionMacros :: [PackageConfig] -> String generatePackageVersionMacros pkgs = concat -- Do not add any C-style comments. See Trac #3389. [ generateMacros "" pkgname version | pkg <- pkgs , let version = packageVersion pkg pkgname = map fixchar (packageNameString pkg) ] fixchar :: Char -> Char fixchar '-' = '_' fixchar c = c generateMacros :: String -> String -> Version -> String generateMacros prefix name version = concat ["#define ", prefix, "VERSION_",name," ",show (showVersion version),"\n" ,"#define MIN_", prefix, "VERSION_",name,"(major1,major2,minor) (\\\n" ," (major1) < ",major1," || \\\n" ," (major1) == ",major1," && (major2) < ",major2," || \\\n" ," (major1) == ",major1," && (major2) == ",major2," && (minor) <= ",minor,")" ,"\n\n" ] where (major1:major2:minor:_) = map show (versionBranch version ++ repeat 0)
如您所见
packageNameString
通过执行 map fixchar
在上面。连字符 ( -
) 替换为下划线 ( _
)。因此,宏可以写成:#if !MIN_VERSION_quickcheck_instances(0,3,17)
instance Arbitrary SBS.ShortByteString where arbitrary = fmap SBS.pack arbitrary
#endif
关于haskell - 如何为名称中包含非字母字符的库定义 MIN_VERSION_𝑙𝑖𝑏 宏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50039809/