2012-06-23 1 views
2

Предположим, у вас есть модуль, который, как вы знаете, безопасен.Как включить Safe Haskell для модуля с обратной совместимостью

Вы хотите отметить его как безопасный Haskell с чем-то вроде {-# LANGUAGE Safe #-} в самом модуле или с чем-то вроде Extensions: Safe в файле cabal. К сожалению, при выполнении любой из этих функций происходит возврат назад совместимости (т. Е. Модуль не будет построен на GHC < 7.2).

Если вся библиотека является безопасной, вы можете просто обернуть директиву расширений в Кабал файл, как это:

if impl(ghc >= 7.2) 
    Extensions: Safe 

Но это работает только для всей библиотеки.

Как вы отмечаете один модуль как безопасный Haskell в обратном совместимом режиме?

+0

'{- # LANGUAGE CPP # -} ; #if __GLASGOW_HASKELL__> = 702; {- # LANGUAGE Safe # -}; # endif'? –

+0

... и я как раз собирался ответить на этот точный фрагмент кода. @DanielFischer прав; он работает, но он не работал бы над версиями более ранних версий GRC, потому что все прагмы «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 должен сделать трюк, и может быть автоматизирована различными способами.)