2012-06-23 16 views
2

假設您有一個知道安全的模塊。如何以向後兼容的方式爲模塊啓用安全Haskell

您想在模塊本身中將其標記爲類似{-# LANGUAGE Safe #-}的Safe Haskell,或者在cabal文件中將其標記爲Extensions: Safe之類的內容。不幸的是,這些中的任何一個都會降低向後兼容性(即模塊不會在GHC < 7.2上生成)。

如果整個庫是安全的,你可以換擴展指令,在這樣的陰謀文件:

if impl(ghc >= 7.2) 
    Extensions: Safe 

但是,這僅適用於整個庫。

如何將單個模塊作爲安全的Haskell向後兼容?

+0

'{ - #語言CPP# - } ; #if __GLASGOW_HASKELL__> = 702; { - #語言安全# - }; #endif'? –

+0

...我正準備提交一份完整的代碼。 @DanielFischer是對的;它可以工作,但它不適用於舊的GHC版本IIRC,因爲所有'LANGUAGE'編譯指示都必須位於當前的一個模塊中(因此,'CPP'在以下行中未能及時啓用') 。您還可以定義一個Cabal標誌,檢測GHC版本,並在編譯時有條件地使用完全不同的文件。 – dflemstr

+0

@DanielFischer這正是我所期待的。謝謝。如果您發佈它,我會接受它作爲答案。 – scvalex

回答

5

如果您不需要支持GHC版本早於6.12(6.12.3是我已經測試了構建with¹最古老的),你可以用預處理器做,

{-# LANGUAGE CPP #-} 
#if __GLASGOW_HASKELL__ >= 702 
{-# LANGUAGE Safe #-} 
#endif 

另外,您可以使用.cabal文件中的標誌來選擇要包含的源文件。

¹對於GHC-6.12,你必須擁有所有{-# LANGUAGE #-}編譯指示由#if一個組中的前#if不森嚴,因爲7.0,他們也可能會出現#if後。

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爲基礎的方法。主要優點是您擁有可供您選擇的所有情況。主要缺點是你現在有兩個文件要保持同步。 (然而,這應該是特別容易實現自動化:像

echo {-# LANGUAGE Safe #-} > has-safe/Foo.hs 
cat no-safe/Foo.hs >> has-safe/Foo.hs 

每個編輯到no-safe/Foo.hs後應該做的伎倆,可以以各種方式實現自動化。)