Проверка версии GHC в коде

Я вношу вклад в Alex, и это, очевидно, зависит от множества библиотек и должно компилироваться для большого количества версий.

Мне нужно использовать функцию, доступную только из GHC 7.6.1, чтобы лучше справляться с ошибкой. Поэтому я хочу использовать #if ... для импорта указанной функции, иначе я буду иметь дело с ошибкой по-другому.

Я видел несколько:

#if __GLASGOW_HASKELL__ >= 610
import Control.Exception ( bracketOnError )
#endif

Итак, я сделал:

#if __GLASGOW_HASKELL__ >= 761
import Text.Read ( readMaybe )
#endif

Мысль о том, что 761 является псевдонимом версии GHC 7.6.1, когда я создаю пакет cabal и проверяю его, функция не импортируется, хотя я использую систему компиляции Glorious Glasgow Haskell, версия 7.8.4.

Итак, после использования программы, чтобы проверить ее, я обнаружил, что 7.8.1 идентифицирует в __GLASGOW_HASKELL__ как 708.

{-# LANGUAGE CPP #-}
module Main where

#if __GLASGOW_HASKELL__ == 708
ver = "==708"
#else
ver = "/=708"
#endif

main = putStrLn $ ver

И запустив его:

$ runhaskell if.hs
==708

Как я могу узнать, какое значение следует использовать для 7.6.1, или есть лучший способ справиться с этим?

Ответ 1

Это описано в разделе раздела 6.11.3.1 руководства пользователя GHC:

Для версии x.y.z для GHC значение __GLASGOW_HASKELL__ является целым числом ⟨xyy⟩ (если ⟨y⟩ - одна цифра, то добавляется начальный ноль, например, в версии 6.2 GHC, __GLASGOW_HASKELL__==602). Дополнительная информация в Политика нумерации версий GHC.

Итак, для 7.6.1 вы должны проверить __GLASGOW_HASKELL__ >= 706. Причиной этого являются версии типа 7.10.x.

Ответ 2

Прочитайте прекрасную документацию:

Для версии xyz GHC значение __GLASGOW_HASKELL__ является целым числом xyy (если y - это одна цифра, то добавляется начальный ноль, например, в версии 6.2 GHC, __GLASGOW_HASKELL__ == 602), Дополнительная информация в Разделе 1.4 "Политика нумерации версий GHC".

При любой удаче __GLASGOW_HASKELL__ будет undefined во всех других реализациях, которые поддерживают предварительную обработку в стиле C.

(Для справки: сопоставимые символы для других систем: __HUGS__ для Объятий, __NHC__ для nhc98 и __HBC__ для hbc.)

NB. Этот макрос задается при предварительной обработке как источника Haskell, так и источника C, включая источник C, сгенерированный из модуля Haskell (т.е. Файлы .hs,.lhs,.c и .hc).

Ответ 3

Как указал Даниэль Вагнер, наиболее правильным способом проверки версии пакета обычно является использование макроса Cabal MIN_VERSION. Например, вы можете использовать

#if MIN_VERSION_base(4,6,0)

чтобы определить, является ли пакет base не менее версией 4.6.0, которая является самой ранней версией с функцией, которую вы ищете.

Пакет base немного странный. Он использовался как GHC, так и ныне несуществующими реализациями Hugs и NHC. Использование макроса Cabal было более переносимым способом проверки версии base. В наши дни GHC является единственным, использующим base, поэтому аргумент переносимости немного менее ясен, но этот подход также имеет преимущество в проверке основных и младших номеров версий.

Так как версии base очень сильно привязаны к версиям GHC, вы можете определить разумную форму возврата MIN_VERSION_base для компиляции без Cabal, используя __GLASGOW_HASKELL__ для оценки версии base. Текущая головка containers условно определяет такое падение.

Update

Как и в GHC 8, сам компилятор взял на себя задачу определения макросов MIN_VERSION. Это здорово, потому что теперь вы можете использовать эти макросы, независимо от того, строите ли вы с Cabal. Нет более уродливых аппроксимаций!