Различные импорты в зависимости от версии зависимостей
У меня есть модуль, который использует Control.Exception в Base < 4, который является Control.OldException в Base >= 4. Как я могу, используя cabal или любой другой инструмент, избавиться от зависимости версии (просто зависите от Base и не Base < 4) и импортировать Control.OldException при использовании Base >= 4 и Control.Exception при использовании Base < 4?
3 ответа:
cabalавтоматически устанавливает определенные определения CPP на основе версии используемых пакетов.Поэтому для вашего случая я бы:
{-# LANGUAGE CPP #-} module Blah where #if MIN_VERSION_base(0,4,0) import Control.OldException #else import Control.Exception #endifЭтот метод прекрасно работает с Кабалом.
(на самом деле, я бы использовал новые исключения и не стал бы утруждать себя поддержкой базы
С Cabal это делается с помощью "флагов" и алгоритма решения ограничений. Пример (из control-monad-exception на Hackage):
Flag extensibleExceptions description: Use extensible-exception package default: False (...) if flag(extensibleExceptions) build-depends: extensible-exceptions >= 0.1 && <0.2, base >= 3.0 && <4 else build-depends: base >= 4 && < 5На машине с более старой версией
base, Cabal попытается решить зависимость сextensibleExceptions False, потерпит неудачу, затем повторит попытку с нейTrueи использует другуюbuild-depends, которая будет успешной. (Вы также можете включить флаг из команды линия.)Http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#configurations документирует этот механизм, а остальная часть страницы описывает другие механизмы, включая прямые условные обозначения, такие как
if impl(ghc >= 6.10.0).
Это языковой агностический ответ, поэтому он может не относиться к вам.
Есть пара вариантов
- оберните оба исключения в Суперэксцепцию, имеющую обе реализации. Дайте ему параметр, который говорит ему, какую реализацию использовать на основе
Base.- исключение Рефактора, являющееся дочерним элементом OldException с переопределенными вызовами. (лучший вариант)