假设您有一个您知道安全的模块。
您希望将模块本身中的{-# LANGUAGE Safe #-}
标记为Safe Haskell,或者在cabal文件中使用Extensions: Safe
之类的标记。不幸的是,这些中的任何一个都会破坏向后兼容性(即模块不会建立在GHC< 7.2上)。
如果整个库都是安全的,您可以将extensions指令包装在cabal文件中,如下所示:
if impl(ghc >= 7.2)
Extensions: Safe
但这只适用于整个图书馆。
如何以向后兼容的方式将单个模块标记为安全Haskell?
答案 0 :(得分:5)
如果您不需要支持早于6.12的GHC版本(6.12.3是我使用¹测试过的最早的版本),您可以使用预处理器来完成,
{-# LANGUAGE CPP #-}
#if __GLASGOW_HASKELL__ >= 702
{-# LANGUAGE Safe #-}
#endif
或者,您可以使用.cabal
文件中的标志来选择要包含的源文件。
¹对于ghc-6.12,您必须在{-# LANGUAGE #-}
之前的#if
之前保护所有#if
个编译区,自7.0以来,它们也可能出现在{#if
之后1}}。
答案 1 :(得分:2)
您可以编写两个版本的模块,并在编译时选择它们。例如:
-- has-safe/Foo.hs
{-# LANGUAGE CPP #-}
foo = 3
-- no-safe/Foo.hs
{-# LANGUAGE CPP, Safe #-}
foo = 3
-- foo.cabal
if impl(ghc >= 7)
hs-source-dirs: has-safe
else
hs-source-dirs: no-safe
与基于CPP
的方法相比,这种方法有优点和缺点。主要优点是您可以使用cabal支持的所有条件进行选择。主要的缺点是你现在有两个文件要保持同步。 (但是,这应该特别容易自动化:类似
echo {-# LANGUAGE Safe #-} > has-safe/Foo.hs
cat no-safe/Foo.hs >> has-safe/Foo.hs
每次编辑no-safe/Foo.hs
之后都应该做到这一点并且可以通过各种方式实现自动化。)